2 // @name Flickr Easy NSID
\r
3 // @namespace http://6v8.gamboni.org/
\r
4 // @description Easily find your and other users NSID on flickr
\r
6 // @identifier http://6v8.gamboni.org/IMG/js/flickreasynsid.user.js
\r
8 // @creator Pierre Andrews (mortimer.pa@free.fr)
\r
9 // @include http://flickr.com*
\r
10 // @include http://www.flickr.com*
\r
13 // --------------------------------------------------------------------
\r
15 // This is a Greasemonkey user script.
\r
17 // To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
\r
18 // Then restart Firefox and revisit this script.
\r
19 // Under Tools, there will be a new menu item to "Install User Script".
\r
20 // Accept the default configuration and install.
\r
22 // --------------------------------------------------------------------
\r
23 // Copyright (C) 2006 Pierre Andrews
\r
25 // This program is free software; you can redistribute it and/or
\r
26 // modify it under the terms of the GNU General Public License
\r
27 // as published by the Free Software Foundation; either version 2
\r
28 // of the License, or (at your option) any later version.
\r
30 // This program is distributed in the hope that it will be useful,
\r
31 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
32 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
33 // GNU General Public License for more details.
\r
35 // The GNU General Public License is available by visiting
\r
36 // http://www.gnu.org/copyleft/gpl.html
\r
38 // Free Software Foundation, Inc.
\r
39 // 51 Franklin Street, Fifth Floor
\r
40 // Boston, MA 02110-1301
\r
46 //update information
\r
48 name: "Flickr Easy NSID",
\r
49 namespace: "http://6v8.gamboni.org/",
\r
50 description: "Easily find your and other users NSID on flickr",
\r
51 identifier: "http://6v8.gamboni.org/IMG/js/flickreasynsid.user.js",
\r
52 version: "0.2", // version
\r
53 date: (new Date("2007-07-12")) // update date
\r
59 if(unsafeWindow.console)
\r
60 unsafeWindow.console.log(arguments);
\r
66 LightWeightBox - Thom Shannon
\r
72 var LightWeightBoxOn=false;
\r
73 var LightWeightBox = function(ele){
\r
75 this.backgroundColor = '#CCC';
\r
78 with (LightWeightBox){
\r
79 prototype.Render = function(){
\r
80 if (!LightWeightBoxOn){
\r
81 bgDiv = document.createElement('div');
\r
82 bgDiv.innerHTML = ''
\r
83 bgDiv.style.backgroundColor = this.backgroundColor;
\r
84 bgDiv.style.position='fixed';
\r
85 bgDiv.style.height='100%';
\r
86 bgDiv.style.width='100%';
\r
88 bgDiv.style.left='0';
\r
89 bgDiv.style.opacity=this.opacity;
\r
90 this.ele.style.position='fixed';
\r
92 document.body.appendChild(this.bgDiv);
\r
93 document.body.appendChild(this.ele);
\r
95 LightWeightBoxOn = true;
\r
97 this.sizeCheck = setInterval(function(){oSelf.CheckSize();},20);
\r
100 prototype.CheckSize = function(){
\r
101 if (this.ele.offsetHeight!=this.currentHeight) {
\r
102 this.offsetTop = (self.innerHeight/2)-(this.ele.offsetHeight/2);
\r
103 this.ele.style.top = this.offsetTop+'px';
\r
104 this.currentHeight=this.ele.offsetHeight;
\r
106 if (this.ele.offsetWidth!=this.currentWidth) {
\r
107 this.offsetLeft = (self.innerWidth/2)-(this.ele.offsetWidth/2);
\r
108 this.ele.style.left = this.offsetLeft+'px';
\r
109 this.currentWidth=this.ele.offsetWidth;
\r
113 prototype.Close=function(oSelf){
\r
114 document.body.removeChild(oSelf.bgDiv);
\r
115 document.body.removeChild(oSelf.ele);
\r
116 LightWeightBoxOn = false;
\r
123 Xpath trickery, from:
\r
124 http://ecmanaut.blogspot.com/2006/07/expressive-user-scripts-with-xpath-and.html
\r
126 function $x( xpath, root )
\r
128 var doc = root ? root.evaluate?root:root.ownerDocument : document;
\r
129 var got = doc.evaluate( xpath, root||doc, null, 0, null ), next;
\r
131 while( next = got.iterateNext() )
\r
132 result.push( next );
\r
137 function $x1(xpath) {
\r
138 return document.evaluate(
\r
142 XPathResult.FIRST_ORDERED_NODE_TYPE, null
\r
146 function foreach( xpath, cb, root )
\r
148 var nodes = $x( xpath, root ), e = 0;
\r
149 for( var i=0; i<nodes.length; i++ )
\r
150 e += cb( nodes[i], i ) || 0;
\r
154 /***********************************************************************
\r
155 * Flickr Localisation
\r
156 **********************************************************************/
\r
158 var FlickrLocaliser = function(locals) {
\r
161 FlickrLocaliser.prototype = {
\r
162 selectedLang: undefined,
\r
163 localisations: undefined,
\r
164 getLanguage: function() {
\r
165 if(!this.selectedLang) {
\r
166 var langA = $x1("//p[@class='LanguageSelector']//a[contains(@class,'selected')]");
\r
168 var matches = /\/change_language.gne\?lang=([^&]+)&.*/.exec(langA.href);
\r
169 if(matches && matches[1]) {
\r
170 this.selectedLang = matches[1];
\r
171 return this.selectedLang;
\r
175 } else return this.selectedLang;
\r
178 init: function(locals) {
\r
179 this.localisations = locals;
\r
182 localise: function(string, params) {
\r
183 if(this.localisations && this.getLanguage()) {
\r
184 var currentLang = this.localisations[this.selectedLang];
\r
185 if(!currentLang) currentLang = this.localisations[this.localisations.defaultLang];
\r
186 var local = currentLang[string];
\r
188 local = this.localisations[this.localisations.defaultLang][string];
\r
190 if(!local) return string;
\r
191 for(arg in params) {
\r
192 var rep = new RegExp('@'+arg+'@','g');
\r
193 local = local.replace(rep,params[arg]);
\r
195 local =local.replace(/@[^@]+@/g,'');
\r
197 } else return undefined;
\r
203 function getObjectMethodClosure(object, method) {
\r
204 return function(arg) {
\r
205 return object[method](arg);
\r
208 function getObjectMethodClosure1(object, method, arg) {
\r
209 return function() {
\r
210 return object[method](arg);
\r
215 var flickreasynsid = function() {this.init();}
\r
217 flickreasynsid.prototype = {
\r
218 mapper: new FlickrLocaliser({
\r
220 'FlickrMail' : 'FlickrMail',
\r
223 'FlickrMail' : 'FlickrMail',
\r
226 'FlickrMail' : 'FlickrMail',
\r
229 'FlickrMail' : 'FlickrMail',
\r
232 'FlickrMail' : 'Flickrcorreo',
\r
235 'FlickrMail' : 'E-mail do Flickr',
\r
238 'FlickrMail' : 'FlickrMail',
\r
241 'FlickrMail' : 'FlickrMail',
\r
243 defaultLang: 'en-us'
\r
247 var menu = document.getElementById('personmenu_contacts_link');
\r
249 var link =document.createElement('a');
\r
250 link.setAttribute('class','block');
\r
251 link.setAttribute('id','tag_person_link');
\r
252 link.setAttribute('href','javascript:;');
\r
253 link.addEventListener('click',getObjectMethodClosure(this,'showNSIDBuddy'),true);
\r
254 link.textContent='NSID?';
\r
256 menu.parentNode.insertBefore(link,menu.nextSibling);
\r
258 this.insertItem(getObjectMethodClosure1(this,'displayNSID',unsafeWindow.global_nsid),'candy_nav_menu_you','Your Profile',"NSID?",false,false);
\r
260 if(document.location.pathname.indexOf('groups') >= 0) {
\r
261 var links = $x1("//table[@id='SubNav']/tbody/tr/td[@class='Section']/p");
\r
263 var a = links.getElementsByTagName('a');
\r
265 for(var i=0;i<a.length;i++) {
\r
266 if(a[i].href.indexOf('?id=') >= 0) {
\r
267 id = a[i].href.split('?id=')[1];
\r
271 var img = links.appendChild(document.createElement('img'));
\r
274 img.src="/images/subnavi_dots.gif";
\r
276 var a = links.appendChild(document.createElement('a'));
\r
277 a.href="javascript:;";
\r
278 a.addEventListener('click',getObjectMethodClosure1(this,"displayNSID",id),false);
\r
279 a.textContent="NSID?";
\r
283 displayNSID: function(nsid) {
\r
284 // create a block element of some kind
\r
285 var boxEle = document.createElement('div');
\r
286 // style it up with a class or inline
\r
287 boxEle.className = 'popup';
\r
288 // create something to act as a close button
\r
289 btnClose = document.createElement('a');
\r
290 btnClose.href='javascript:;';
\r
291 btnClose.innerHTML='<img style="margin: 0; padding: 0; border:0px !important; vertical-align: top;" src="http://flickr.com/images/window_close_grey.gif" alt="close"/>';
\r
292 btnClose.title = "close";
\r
294 // add close button to block element
\r
295 boxEle.appendChild(btnClose);
\r
296 // create box with block element
\r
297 var lwBox = new LightWeightBox(boxEle);
\r
298 // optional bg color and opacity
\r
299 boxEle.style.paddingTop= '10px';
\r
300 boxEle.style.width= '350px';
\r
301 boxEle.style.paddingBottom = '10px';
\r
302 boxEle.style.backgroundColor = '#fff';
\r
303 boxEle.style.border = '1px solid black';
\r
304 // attach close event and add your own code
\r
305 btnClose.addEventListener('click',function(){
\r
306 // you have to pass box object into event
\r
307 // because of the js event scoping
\r
308 lwBox.Close(lwBox);
\r
309 // false to cancel link
\r
312 btnClose.setAttribute('style','float:right;margin-bottom:10px;margin-right:5px;');
\r
314 var title = boxEle.appendChild(document.createElement('div'));
\r
315 title.setAttribute('style',"padding:12px;background-color: #EEEEEE;clear:both;font-size: 14px;margin-bottom:10px");
\r
316 title.innerHTML = '<h3 style="margin:0;">NSID:</h3>';
\r
318 dial = boxEle.appendChild(document.createElement('textarea'));
\r
319 dial.textContent = nsid;
\r
320 dial.setAttribute('style',"clear:both; width:70%;overflow:auto;margin-left:15%;");
\r
324 //insert a new menu item in on of the main menus
\r
325 // href the link on that element or a javascript function to call
\r
326 // menu is the id of the main menu where to insert the new menu item (e.g. 'candy_nav_menu_you')
\r
327 // item is the item "title" before which to insert the new menu item (or to replacE) (e.g. 'Your Sets')
\r
328 // title is the title of your new item
\r
329 // replace is a boolean to know if we replace 'item' or just add a new one
\r
331 //returns: the a element created
\r
332 insertItem: function(href,menu,item,title,replace,line_above) {
\r
334 var menu_you = document.getElementById(menu);
\r
335 var you_a = menu_you.getElementsByTagName('a');
\r
336 var your_set = '';
\r
337 item = this.mapper.localise(item);
\r
338 for(var i=0;i<you_a.length;i++) {
\r
339 if( you_a[i].innerHTML == item ) {
\r
340 your_set = you_a[i];
\r
346 GM_log('impossible to find insertion point');
\r
350 var batch = document.createElement('a');
\r
351 if(typeof(href) == "function") {
\r
352 batch.addEventListener("click",href,true);
\r
353 batch.href = 'javascript:;';
\r
356 batch.innerHTML = title;
\r
357 if(line_above) batch.className = "menu_item_line_above";
\r
358 your_set.parentNode.insertBefore(batch, your_set);
\r
359 if(replace) your_set.parentNode.removeChild(your_set);
\r
363 showNSIDBuddy: function(ev) {
\r
364 var block = ev.target.parentNode;
\r
365 var matches = /messages_write\.gne\?to=([^"]*)"/.exec(block.innerHTML);
\r
367 this.displayNSID(matches[1]);
\r
373 //======================================================================
\r
376 window.addEventListener("load", function () {
\r
379 // update automatically (http://userscripts.org/scripts/show/2296)
\r
380 win.UserScriptUpdates.requestAutomaticUpdates(SCRIPT);
\r
383 var flickrgp = new flickreasynsid();
\r