// ==UserScript==
// @name iStock Stats View
// @namespace theasis
// @match http://*.istockphoto.com/my_uploads.php*
// @match https://*.istockphoto.com/my_uploads.php*
// @match http://*.istockphoto.com/file_downloads.php*
// @match https://*.istockphoto.com/file_downloads.php*
// @version 0.0.3
// iStockPhoto greasemonkey script (c) Martin McCarthy 2013
// ==/UserScript==
// Better views of iStock contributor statistics
// v0.0.1 Martin McCarthy 2013-04-25
// initial version
// v0.0.2 Martin McCarthy 2013-05-02
// much prettier charts using the raphael and morris libraries
// raphael Copyright (c) 2008 Dmitry Baranovskiy
// raphael license: http://raphaeljs.com/license.html
// morris Copyright (c) 2013, Olly Smith
// morris license: http://www.oesmith.co.uk/morris.js/#license
// v0.0.3 Martin McCarthy 2013-05-02
// links to graphs from my_uploads
function main() {
recordSalesData = function(age,size,dlType,royalty) {
// console.log(" size:" + size + " type:" + dlType + " royalty:" + royalty + " age:" + age);
if (!salesData[age]) {
salesData[age]={dl:0,royalty:0};
}
salesData[age].dl++;
salesData[age].royalty+=royalty;
};
processTableRow = function() {
var cols = jQ(this).find("td");
var date = cols.eq(0).text();
var age = dateStrToAge(date);
var size = cols.eq(1).text().trim();
if (age<0) age = dateStrToAge(size);
var dlType = cols.eq(2).text();
var royStr = cols.length==3 ? dlType : cols.eq(3).text(); // e.g. GI page has royalty in col2
var royalty = -1;
var match=/\$(\d+\.\d+)/.exec(royStr);
if (match) {
royalty=parseFloat(match[1]);
}
if (royalty>0) recordSalesData(Math.floor(age),size,dlType,royalty);
};
dateStrToAge = function(dateStr) { // parse 23/02/2009 8:16 AM MST into an age in days
var age=-1;
var match=/(\d{2})\/(\d{2})\/(\d{4})\s+(\d+):(\d+)\s+([AP])M\s+M([DS])T/.exec(dateStr);
if (match && match.length==8) {
var dy=match[1];
var mo=parseInt(match[2]);
var yr=match[3];
var hr=parseInt(match[4]);
var mi=match[5];
var ap=match[6];
var ds=match[7];
if (ap=='P' && 12>hr) hr+=12;
if (ap=='A' && 12==hr) hr=0;
var d = new Date();
d.setUTCFullYear(yr,mo-1,dy);
d.setUTCHours(hr);
d.setUTCMinutes(mi);
d.setHours(d.getHours()+(ds=='S'?7:6));
var days=d.getTime()/(1000*3600*24);
age = window.theasisData.now-days;
}
if (age>window.theasisData.oldest) {
window.theasisData.oldest=age;
}
return age;
};
normalisedMonth = function(age) { // return stats for the normalised month ending 'age' days ago
var dls=0;
var royalty=0;
for (var i=0;i<28;++i) {
if (salesData[age+i]) {
dls++;
royalty+=salesData[age+i].royalty;
}
}
return {age:""+(1-age)+" days", days:age, dls:dls, royalty:royalty, royPerDl:(dls?royalty/dls:0)};
};
drawSalesGraph = function() {
var nDays=52*7;
var colWidth=2;
var colHeight=100;
var nMonth=[];
var maxDls=0;
var maxRoyalty=0;
var maxRoyPerDl=0;
var graphContainer=jQ("#theasis_statsView_graph");
if (graphContainer.length) {
graphContainer.remove();
}
var statsDiv = jQ("
").css({'background-color':'#f0f0ff',margin:'10px'});
var statsBox=jQ("#theasis_statsView_popupStatsBox");
if (statsBox.length) {
statsBox.append(statsDiv);
} else {
jQ("div.rnd:first").after(statsDiv);
}
for(var i=nDays+1;i>0;i-=7) {
nMonth.push(normalisedMonth(i));
}
Morris.Line({
element: 'theasis_statsView_graph',
data: nMonth,
smooth: true,
xkey: 'age',
ykeys: ['royalty','dls'],
labels: ['Royalty/mon','DLs/mon'],
events: ['-28','-56','-84','-112','-140','-168'],
lineColors: ['#dd6622','#88aa33'],
hoverCallback: function(index,options,content) {
// console.log(options);
// console.log(content);
var txt = jQ("");
txt.append(jQ("
"+((options.data[index].days-1)/7) + " weeks ago
").css({color:'#222','font-weight':'bold','margin-left':'10px'}));
txt.append(jQ("
$"+options.data[index].royalty.toFixed(2) + "/month
").css({color:options.lineColors[0],'font-weight':'bold','margin-left':'10px'}));
txt.append(jQ("
"+options.data[index].dls + " DLs/month
").css({color:options.lineColors[1],'font-weight':'bold','margin-left':'10px'}));
var per = options.data[index].dls ? (options.data[index].royalty/options.data[index].dls).toFixed(2) : "0.00";
txt.append(jQ("
Average: $"+ per + "/DL
").css({color:'#762','font-weight':'bold','margin-left':'10px'}));
return txt;
},
parseTime: false
});
};
doTableToData = function(data) {
var html;
if (data) html=jQ(data);
var table=jQ("table.reporttable tr:gt(0)",html);
if (!table.length) {
table=jQ("div.rnd:first table:first tr:gt(0)",html);
}
table.each( processTableRow );
drawSalesGraph();
if (window.theasisData.oldest < 400) {
var paginator = jQ("div.paginator:first a[accesskey='n']",html).eq(0).attr('href');
if (paginator) {
console.log("Getting next page: " + paginator);
jQ.ajax({
url:paginator,
success:doTableToData
});
}
}
};
doMyUploadsLinks = function() {
var table=jQ("#wrapper table.data:first");
var cols=table.find("tr:first th");
var dlCol=-1;
for (var i=0;i
-1 && href.indexOf('order=DownloadCount')>-1) {
dlCol=i;
break;
}
}
if (dlCol>-1) {
table.find("tr:gt(0)").each(function() {
var cols = jQ(this).find("td");
var fileLink = cols.eq(0).find("a[href*='file_closeup_edit']").attr('href');
var fileid=0;
if (fileLink) {
var match=/id=(\d+)/.exec(fileLink);
if (match) {
fileId=match[1];
}
}
if (fileId) {
jQ(this).find("td").eq(dlCol).each(function() {
if (parseInt(jQ(this).text())>0) {
var id=fileId;
jQ(this).append(jQ("
")).append(jQ("").css({cursor:"pointer"}).click(function(){
jQ("#theasis_statsView_popupStatsBox").remove();
var statsDiv = jQ('').attr( {style:'position:fixed;left:100px;top:100px;z-index:10000;background-color:#f0f8ff;border:2px solid #333;padding:4em; width:720px;height:400px;overflow-y:scroll;'} ).stop().hide();
var closeButtonTop = jQ('').attr({
src: "/static/images/blank.gif",
id: "theasis_StatsBoxCloseButtonTop"});
closeButtonTop.click(function () { jQ('#theasis_statsView_popupStatsBox').hide('fast'); }).addClass("modalClose").appendTo(statsDiv);
statsDiv.appendTo('body');
statsDiv.show('fast');
salesData=[];
window.theasisData.oldest=0;
jQ.ajax({
url:"http://www.istockphoto.com/file_downloads.php?id="+id,
success:doTableToData
});
}));
}
});
}
});
}
};
if (!window.theasisData) window.theasisData={};
var now=new Date();
salesData=[];
window.theasisData.now = now.getTime()/(1000*3600*24);
window.theasisData.oldest = 0;
var loc = window.location.pathname;
if (loc.indexOf("/file_downloads.php")>-1) {
doTableToData();
} else if (loc.indexOf("/my_uploads.php")>-1) {
doMyUploadsLinks();
}
}
// load jQuery and kick off the meat of the code when jQuery has finished loading
function addJQuery(callback) {
var chromestore=false;
if (chromestore) {
// chrome store install
window.jQ=jQuery.noConflict(true);
main();
} else {
// manual install
var script = document.createElement("script");
script.setAttribute("src", "http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.js");
script.addEventListener('load', function() {
if (window.raphloaded && window.morloaded) {
var script = document.createElement("script");
script.textContent = "window.jQ=jQuery.noConflict(true);(" + callback.toString() + ")();";
document.body.appendChild(script);
}
window.jqloaded=true;
}, false);
document.body.appendChild(script);
var scriptR = document.createElement("script");
scriptR.setAttribute("src", "http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js");
scriptR.addEventListener('load', function() {
if (window.jqloaded && window.morloaded) {
var script = document.createElement("script");
script.textContent = "window.jQ=jQuery.noConflict(true);(" + callback.toString() + ")();";
document.body.appendChild(script);
}
window.raphloaded=true;
}, false);
document.body.appendChild(scriptR);
var scriptM = document.createElement("script");
scriptM.setAttribute("src", "http://cdn.oesmith.co.uk/morris-0.4.2.min.js");
scriptM.addEventListener('load', function() {
if (window.raphloaded && window.jqloaded) {
var script = document.createElement("script");
script.textContent = "window.jQ=jQuery.noConflict(true);(" + callback.toString() + ")();";
document.body.appendChild(script);
}
window.morloaded=true;
}, false);
document.body.appendChild(scriptM);
}
}
addJQuery(main);