2 // @name Flickr More Sparkles
3 // @namespace http://6v8.gamboni.org/
4 // @description Add Sparkle lines for stats of individual photos
6 // @identifier http://6v8.gamboni.org/IMG/js/flickr_more_sparkles.user.js
8 // @creator Pierre Andrews (mortimer.pa@free.fr)
9 // @include *flickr.com/photos/*
10 // @include *flickr.com
11 // @include *flickr.com/
12 // @include *flickr.com/activity*
13 // @include *flickr.com/photos/*
14 // @include *flickr.com/photos/*/stats*
15 // @exclude *flickr.com/photos/*/alltags*
16 // @exclude *flickr.com/photos/organize*
19 // --------------------------------------------------------------------
21 // This is a Greasemonkey user script.
23 // To install, you need Greasemonkey: http://greasemonkey.mozdev.org/
24 // Then restart Firefox and revisit this script.
25 // Under Tools, there will be a new menu item to "Install User Script".
26 // Accept the default configuration and install.
28 // --------------------------------------------------------------------
29 // Copyright (C) 2008 Pierre Andrews
31 // This program is free software; you can redistribute it and/or
32 // modify it under the terms of the GNU General Public License
33 // as published by the Free Software Foundation; either version 2
34 // of the License, or (at your option) any later version.
36 // This program is distributed in the hope that it will be useful,
37 // but WITHOUT ANY WARRANTY; without even the implied warranty of
38 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
39 // GNU General Public License for more details.
41 // The GNU General Public License is available by visiting
42 // http://www.gnu.org/copyleft/gpl.html
44 // Free Software Foundation, Inc.
45 // 51 Franklin Street, Fifth Floor
46 // Boston, MA 02110-1301
54 name: "Flickr More Sparkles",
55 namespace: "http://6v8.gamboni.org/",
56 description: "Add Sparkle lines for stats of individual photos",
57 identifier: "http://6v8.gamboni.org/IMG/js/flickr_more_sparkles.user.js",
58 version: "0.1", // version
59 date: (new Date("2008-12-10")) // update date
64 /***********************************************************************
66 **********************************************************************/
68 var FlickrLocaliser = function(locals) {
71 FlickrLocaliser.prototype = {
72 selectedLang: undefined,
73 localisations: undefined,
74 getLanguage: function() {
75 if(!this.selectedLang) {
76 var langA = $x1("//p[@class='LanguageSelector']//a[contains(@class,'selected')]");
78 var matches = /\/change_language.gne\?lang=([^&]+)&.*/.exec(langA.href);
79 if(matches && matches[1]) {
80 this.selectedLang = matches[1];
81 return this.selectedLang;
85 } else return this.selectedLang;
88 init: function(locals) {
89 this.localisations = locals;
92 localise: function(string, params) {
93 if(this.localisations && this.getLanguage()) {
94 var currentLang = this.localisations[this.selectedLang];
95 if(!currentLang) currentLang = this.localisations[this.localisations.defaultLang];
96 var local = currentLang[string];
97 if(!local) return string;
99 var rep = new RegExp('@'+arg+'@','g');
100 local = local.replace(rep,params[arg]);
102 local =local.replace(/@[^@]+@/g,'');
104 } else return undefined;
109 /*****************************Flickr Localisation**********************/
114 if(unsafeWindow.console)
115 unsafeWindow.console.log(arguments);
121 Xpath trickery, from:
122 http://ecmanaut.blogspot.com/2006/07/expressive-user-scripts-with-xpath-and.html
124 function $x( xpath, root )
126 var doc = root ? root.evaluate?root:root.ownerDocument : document;
127 var got = doc.evaluate( xpath, root||doc, null, 0, null ), next;
129 while( next = got.iterateNext() )
135 function $x1(xpath, root) {
136 var doc = root ? root.evaluate?root:root.ownerDocument : document;
137 return document.evaluate(
141 XPathResult.FIRST_ORDERED_NODE_TYPE, null
145 function foreach( xpath, cb, root )
147 var nodes = $x( xpath, root ), e = 0;
148 for( var i=0; i<nodes.length; i++ )
149 e += cb( nodes[i], i ) || 0;
155 function getObjectMethodClosure(object, method) {
156 return function(arg) {
157 return object[method](arg);
162 var flickrmoresparkles = function() {this.init();}
164 flickrmoresparkles.prototype = {
166 localiser: new FlickrLocaliser({
167 'en-us' : {'photo_stats': 'Photo stats'},
172 makeSpark: function(url, insert, withLink, fill,bg) {
176 headers: { 'Cookie': document.cookie },
177 onload:function(details) {
178 var start = details.responseText.indexOf("F.photoViews = {");
180 var end = details.responseText.indexOf("</script>",start);
181 var code = details.responseText.substring(start,end).replace("F.photoViews = {","").replace("foreGraph:","");
182 code = code.substring(0,code.lastIndexOf("]"))+"]";
183 var evaled = eval(code);
187 for(i=0;i<evaled.length;i++) {
188 var val = parseInt(evaled[i].views);
189 if(isNaN(val)) val =0;
200 values=values.substring(1);
201 var imgtxt = "<img src=\"http://chart.apis.google.com/chart?"
204 + "&chs="+(fill?"100x32":"81x22")
208 + "&chm=o,990000,0,81,4"+(fill?"|B,EBEAFF,0,0,0":"")
210 + "&chxs=1,990000,1,0,_"
212 + "&chxp=0,"+(val*100/max)
213 +(bg?"&chf=bg,s,f5f5f5":"")
216 insert.innerHTML += "<a href="+url+">"+imgtxt+"</a>";
218 insert.innerHTML +=imgtxt;
222 if(insert.innerHTML == '') {
223 insert.innerHTML = '0';
232 if(document.title == "Flickr: Your Photostream"){
234 foreach("//p[@class='Activity']",function(el) {
235 var ael = $x1("a",el);
236 self.makeSpark(ael.href+"/stats",el,true);
238 } else if(document.title.indexOf('Stats for your account')>=0) {
241 foreach("//div[@class='yesterday']/table//span[contains(@class,'photo_container')]/a",function(el) {
243 var ael = $x1("td[@class='views']",el.parentNode.parentNode.parentNode);
245 self.makeSpark(el.href,ael,false,false,(++cnt%2>0));
247 } else if(document.title.indexOf('All your photos and videos') >= 0) {
250 foreach("//table//span[contains(@class,'photo_container')]/a",function(el) {
252 var ael = $x1("td[@class='yesterday']",el.parentNode.parentNode.parentNode);
254 self.makeSpark(el.href+"/stats",ael,false,false,(++cnt%2>0));
257 var statIT = $x1("//td[@class='RHS']/ul/li[3]/a");
258 if(!statIT || statIT.innerHTML != "Photo stats") {
259 statIT = $x1("//td[@class='RHS']/ul/li[2]/a");
261 if(statIT && statIT.innerHTML == "Photo stats") {
262 var url = statIT.href;
263 this.makeSpark(url,statIT);
265 var stats = $x1("//a[@title='Your Stats']");
267 stats.innerHTML = '';
268 this.makeSpark(stats.href,stats,false,true);
270 foreach("//ul[contains(@class,'tt-stats-list')]/li/p/a",function(el) {
271 var ael = $x1("div[@class='tt-stats-count']",el.parentNode.parentNode);
273 self.makeSpark(el.href,ael);
282 //======================================================================
285 window.addEventListener("load", function () {
288 // update automatically (http://userscripts.org/scripts/show/2296)
289 win.UserScriptUpdates.requestAutomaticUpdates(SCRIPT);
292 var flickrgp = new flickrmoresparkles();