// ==UserScript== (by Edward Lee)
// @name Firefox Download Counter
// @namespace http://ed.agadak.net/
// @description Put an animated counter on every page (click to fade, click/drag to move, double click firefox to close)
// ==/UserScript== (edilee gmail)
(function() {
if (top.location != document.location) return;
if (document.contentType != 'text/html') return;
window.addEventListener('load', function() {
if (document.getElementById('ffCounter') != null) return;
var newScript = document.createElement('style');
// no literal strings of html yet.. http://www.mozdev.org/pipermail/greasemonkey/2005-April/001309.html
newScript.innerHTML = '\
div.ffContainer { position: fixed; top: 1px; right: 1px; } \
div#ffCounter { width: 0px; height: 31px; position: relative; top: 0px; left: 0px; -moz-opacity: .1; } \
div#ffCounter div.left { position: absolute; top: 0px; left: 0px; width: 10px; height: 31px; background: url(data:image/gif;base64,R0lGODlhCgAfAMQAAGaZmX+pqZ6/v7PMzMDa2sXd3b7V1dHk5LzNzdfn587d3d7s7NXe3ubu7u/29t7g4P////f39+/v7+bm5v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABQALAAAAAAKAB8AAAWCICUOZDmMg5KsKzUYDiTPZDTfw3Hj0k7HPojCFmwQg0iIMcJsMhUNh3QqRSyoVMGhwe1yA4WFeCwGGFjohPnAbrMBKYV8roAX7vg7nMDv8/d+fXZ5eHB0dAAIDIuMi4mNjYkPk5STAAITmZqZAAATXl0UAAEMEqanop0CcXIiqZ2wIQA7); } \
div#ffCounter div.mid { position: absolute; top: 0px; left: 10px; right: 31px; height: 31px; background: url(data:image/gif;base64,R0lGODlhAQAfAMQAAGaZmbPMzMDa2sXd3dHk5Nfn587d3d7s7NXe3ubu7u/29t7g4P////f39+/v7+bm5v///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABAALAAAAAABAB8AAAUWYFAwZEk2ipIcBWEMgjAYCLI8iWMAIQA7); } \
div#ffCounter div.right { position: absolute; top: 0px; right: 0px; width: 31px; height: 31px; background: url(data:image/gif;base64,R0lGODlhHwAfAOYAALOz0lZWY8jI1pOVwERJiwAKSScwXQAWYCk7ZlhojwAlbD9KYAAwdwA9kTFtrwBIjwBDhwA8egAzZgBTmQAhPgBepQ91tDN5pQBwsCJYdwBmmQJFaACBuhGRyqTH1wCSxxin26fP3QCZzAul1xhzjxy66T3J8WPM7DZpd6yztanY5K2/wlyIi2aZmX+pqZ6/v7PMzMDa2sXd3b7V1dHk5LzNzdfn587d3d7s7MzX19Xe3ubu7u/29t7g4ISnpZ+pnkZKQsTGu/3srtzFm8Gznda9nLWqnf/MmZ6QgsVrGd1/JMacdOp6GNCERf+3euRvFt5sFtJxJvmeVeBiDvKAMeWdbK13UvBmE+NkFO90JYpKIfKFQLdrOumKT96UZeRSAedaCOFaCvZpGfBpH+dsJ/+IQd9TCLlZJZpQK7d8Xt5KBtNHB8FNGdqPbJU4EcwzAKpzYb8xB9U7DLKhnG5MRakXAMUgB74WB5IbEEw2Nf////f39+/v78zMzP///wAAACH5BAEAAH4ALAAAAAAfAB8AAAf/gDCCg4SFhod+iTaLjI2OMwAAHpOUISoqgol6m5ybe50ABAoRDxMTFRUWFh0gJSczMH6dm3xLfZwDCqMQEKWnqRYlwiawnZ9eSTl6OwkHCgwMEby+qBatwpizRFBMRQIEzrrQEaQJcz8X1sKuMJx7e15MTFwLBQf34hEJQ0JOKBMd1oEAEcNdkCbymGixZwCBQwRIjjiREgBChREDQXToYMPdnCRMnkyZgiZNFScou5ShIsaKBgwdRozYuJGHJz5IkmBZY4ZMmZ9lpEjJMmaMGBYiZCql+W4PHz5p2MiRU/SK1atFxYAJICKpUqU4ePDY0QNOHJ5mRoJZu/bqFzwa/0Z0/Toixo4dOMquCZN2ZBi2bK+YqYOHxIcPXROvuIsjSBQsI588AUx5cB03dOgAIZH4BQ4cOpZAgTJFiZIwXygDjhPnzZs1boAc/uBi0cHTpaekVs12zWsyToaw4MDhQwsaNIgomaJm9JcwU3ivNRPFiZAgKDQQN35jhugvX6CECUNa+pUpXo4g2TABA3EOLWQcHAk+PBTzY7JksbLhwcv3LcTg2GiofbGcalbpRwUVXGzwEgYQYhDgCnAwodsXU0CxW2D5ZbHgShlUECGELdyQAhdMFEjahldg4SIZMG6xhRQZnDJiCzkYcYaGGD6BxYZq3CHkHXhQQEEeTdSIyriSOBoh1XMZ8ghGkEPekYcEEpBTypKoNMnGGxheCB4Yb9xhx5l25BHNNKZwieMcbIwHXX3gvYGmHXKwIUEDD/hiiikOvFnHGyKJWadrU8lxxRkI8Nnnowv40IIOc+BhxxNpFQheoolaxQYQETTQQAR0cNGFCy30kIKlUKiBBY/gqcGpGmFYhcUZaKARRRZlSOpHDjXMkUYbXhRrrBdtJKtsslU02ywRP7QgrR/SVmvttdhm20IifgQCADs=); } \
div.ffScreen { position: absolute; top: 0px; left: 0px; z-index: 2; width: 100%; height: 100%; } \
div.ffScreen span { position: absolute; top: 0px; left: 0px; width: 100%; height: 100%; -moz-opacity: 0; } \
div#ffNumbers { position: relative; top: 5px; left: 4px; padding-top: 3px; height: 20px; overflow: hidden; z-index: -1; } \
div#ffNumbers img { vertical-align: top; background-repeat: no-repeat; }';
document.getElementsByTagName('head')[0].appendChild(newScript);
var newDiv = document.createElement('div');
newDiv.className = 'ffContainer';
newDiv.innerHTML = '
';
document.body.appendChild(newDiv);
var removed = false;
// click fader, click n drag movement, double click closer
with (document.getElementById('ffCounter')) {
var unfade = false, fading = false;
var fadeRate = .1, fadeTime = 20;
var maxOpacity = 1, minOpacity = .1;
style.MozOpacity = minOpacity;
function fade() {
fading = true;
function doFade(inc) {
style.MozOpacity = Math.min(.999, Math.max(0, style.MozOpacity - 0 + inc)); // image flickers when it hits 1, so go to .999
setTimeout(function() { fade(); }, fadeTime);
}
if (unfade == true && style.MozOpacity < Math.min(1, maxOpacity)) {
doFade(fadeRate);
} else if (unfade == false && style.MozOpacity > Math.max(0, minOpacity)) {
doFade(-fadeRate);
} else {
fading = false;
}
}
var lastClick = false, movable = false;
addEventListener('mousedown', function(e) {
movable = {"x": e.screenX, "y": e.screenY, "startX": style.left, "startY": style.top }; // style is of ffCounter
if (e.layerX > intVal(style.width) - 31) { // clicked on the firefox part of the image
var time = new Date().getTime();
if (lastClick && time - lastClick < 500) {
style.display = parentNode.style.display = 'none'; // remove container.. and counter? too (not sure why the counter stays)
removed = true;
// parentNode.parentNode.removeChild(parentNode); // remove ffCounter's parent ffContainer
} else {
lastClick = time;
}
}
}, false);
window.addEventListener('mouseup', function(e) {
if (movable.x == e.screenX && movable.y == e.screenY) { // fade toggle if not moved
unfade = !unfade;
if (fading == false) { // only fade if not already fading
fade();
}
}
movable = false;
}, false);
window.addEventListener('mousemove', function(e) {
if (movable != false) {
with (style) { // this is ffCounter's style
top = (e.screenY - intVal(movable.y) + intVal(movable.startY)) + 'px';
left = (e.screenX - intVal(movable.x) + intVal(movable.startX)) + 'px';
}
}
}, false);
// addEventListener('mouseover', function() { unfade = true; fading || fade(); }, true);
// addEventListener('mouseout', function() { unfade = false; fading || fade(); }, true);
}
// various images in base64 data uri encoding
var images = {
'blank': 'data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
'comma': 'data:image/gif;base64,R0lGODlhAwASAKIAAAAIPgAIPQAKRwAKRgAIOx0mXjxEdP///yH5BAEAAAcALAAAAAADABIAAAMOeLrc/pCZcoo4g5xwgEoAOw==',
'0': 'data:image/gif;base64,R0lGODlhCgAPANUAAAAJRQAJRAAHNQAGLw0WUhMcV0JJeEZNe0dOfFthigAKSQAKRgAJQwAJQAAIPAAIOgAIOAAINwAHMgAHMAAGLAAGKQAGKAAFJQoUUBYfWRskXCIrYSQtYyUuYy83azE5bDQ8bjpCcklQfUtSf1hfiGVrkf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACYALAAAAAAKAA8AAAZLQJNwSCSWEqOiiSQygTTFwxATGCI+Q0Vj6CkMF44hhxh4CA0bIgAiDEGHDIHw8xY2JMJOBs4WEhRDEANfDEMTRQ4RJhMVShQWF0RBADs=',
'1': 'data:image/gif;base64,R0lGODlhCgAPAMQAAAAJRQAJRAAIPQAHNQ0WUhEaVUZNe1thil9ljQAKSQAKSAAIPAAIOwAIOgAIOAAHNAAHMgAHMAAGKwAFJQAFIwELSgQOTBYfWSQtYyYvZDI6bTtDcz5GdUpRfmNpkP///yH5BAEAAB8ALAAAAAAKAA8AAAUz4CeOZClupnhgpodwSmmI15JmAZQSTfolA18lmCo4Uh2CTwPwXQSpS+BRsgQYkQlFIgoBADs=',
'2': 'data:image/gif;base64,R0lGODlhCgAPAMQAAAAJRAAIPgAHNgAFJykxZkRLegAKSQAKSAAKRwAJQgAJQQAJPwAIOwAIOQAIOAAINwAHMwAHMAAGKhcgWRkiWxwlXSUuYyw0aC83azhAcUxTf1JZhFNahFVchv///wAAACH5BAEAAB4ALAAAAAAKAA8AAAUzoCeOZMl1Rell4mWQ1jglqng0tRdEuZMDghoFkCPkNLlObkNikDCVw+IBGSEUjohkMAoBADs=',
'3': 'data:image/gif;base64,R0lGODlhCgAPAMQAAAAJRQAJRAAHNwAHNQ0WUhAZVCcvZSgwZgAKRwAKRgAJQQAJPwAJPgAIOwAHMgAGLAIMSgUPTQgSTxghWhskXB8oXy42ai83azY+cDhAcT5GdUxTf09Wgf///wAAAAAAACH5BAEAAB0ALAAAAAAKAA8AAAUwYCeOZLlxWtlh4gGpIoXAHRHQEW3Ql1XRnUmCVljQEAJa4wFTOEgZESBJkgAYA1IIADs=',
'4': 'data:image/gif;base64,R0lGODlhCgAPANUAAAAJRAAHNgAGLgAFJwAFJgAEIBAZVEBHd0JJeFxiiwAKSAAKRwAKRgAJQwAJQAAJPwAJPgAHNAAHMgAHMAAGKQAFJQAFIwELSgQOTBkiWy42ajE5bDQ8bk1UgFJZhFhfiFlgiWdtk2pwlW1zl////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACQALAAAAAAKAA8AAAY+QJJwSCwOOUahJ5MMbQDGUQdjFIE0D2OCZAgUP0LGhIg4CB0ComYISQsXl4uiERlUjAFKkiQh7AUWexQFQ0EAOw==',
'5': 'data:image/gif;base64,R0lGODlhCgAPAMQAAAAJRQAJRAAHNREaVRIbVikxZl9ljQAKRgAJQwAJQgAJQQAJQAAJPwAJPgAIOwAIOgAIOAAINwAHNAAHMgELSgIMSgcRTggSTwoUUAsVURwlXS42ajc/cElQff///wAAACH5BAEAAB4ALAAAAAAKAA8AAAUxoCeOI0Z6RldQzMkRSOSe5EaPWnaL1rF7GMVusNhVHrvEZOfYBSQkjggAOV0ADcEpBAA7',
'6': 'data:image/gif;base64,R0lGODlhCgAPANUAAAAJRQAJRAAIPQAHNgAHNQAGLgAFKAAFJxIbVhMcVykxZkBHd1xii11jiwAKSQAJQQAJQAAJPgAIPAAIOwAIOAAGLAAFJAELSgUPTRQdVxUeWBskXB4nXh8oXzlBcjpCcj9HdklQfU5VgVVchmpwlXB2mf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACYALAAAAAAKAA8AAAZDQJNwSCwKMw7jgmM0jZomUqhZakAZoA0mQBR9EkKIZOjpDCOUoQIxFBCGmqRwUBheuMLCYQh4DCtFEwMmekYVBhZEQQA7',
'7': 'data:image/gif;base64,R0lGODlhCgAPAMQAAAAJRAAIPgAHNQAFKA4XUxAZVENKeQAKSQAKRwAKRgAJQwAJQgAIOwAIOAAHMwAGLAAGKgQOTAYQTQwWUhwlXR0mXiMsYjA4a1hfiGFnjv///wAAAAAAAAAAAAAAAAAAACH5BAEAABoALAAAAAAKAA8AAAUtoCaO5JhlmFEhwHhZRcI443SMT0kOugj1GgFQEwAShhIgZRgBFhZARQPI6IUAADs=',
'8': 'data:image/gif;base64,R0lGODlhCgAPANUAAAAJRQAJRAAIPgAIPQAHNgAFJwAFJigwZkBHd0FId0VMegAKSQAKRwAJPgAIPAAIOgAIOQAINwAHMQAHMAAGLQAGLAAGKgAGKQAFJAAFIwMNSxYfWR8oXyEqYTQ8bjU9bzc/cDhAcUlQfUpRflBXglFYg1deh1ZdhlhfiGFnjmJoj////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACsALAAAAAAKAA8AAAZIwJVwSCyiEIfiSqUQBoip07BBNImGEOIoJIwoDxqqkrMYKEErhqNI8ggfkmEpMSRQhp/OcHIZbhZDFgZDAAJCFRhFEhYFGURBADs=',
'9': 'data:image/gif;base64,R0lGODlhCgAPANUAAAAJRQAJRAAIPgAIPQAHNgAHNQAGLwAFKAAEIA0WUigwZlxii2BmjgAKRwAJQwAJQgAJQQAJPwAIPAAHNAAHMwAHMAAGKwAGKQAFIwcRTgsVURkiWxwlXSIrYTc/cDhAcT9HdkxTf05VgVJZhFVchmdtk////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACYALAAAAAAKAA8AAAZEQJNwSCSWFqGiiTEyeThF0jABGJJEwwxkCPoMG5KhojN8EIabzXBQGWoSQsfkQmwEIoWDUnhB7A0YeyYWewIUSg1bSkEAOw=='
};
// set up the initial value of the counter
var lastValueRev; // reversed last value
function prepCounter(num) {
if (lastValueRev != undefined) { // only prep once
return;
}
lastValueRev = reverseNum(num);
var len = getCommaSize(num);
updateWidth(len);
with (document.getElementById('ffNumbers')) {
for (var i = 0, j = 0; i < len; i++) {
var img = document.createElement('img');
if (isCommaSpot(len - i)) { // it's a comma
img.src = images['comma'];
img.className = 'comma'
img.style.position = 'relative';
img.style.left = '-1px';
} else {
img.id = 'ffNumber' + (num.length - j - 1);
img.src = images[num[j]];
j++;
}
appendChild(img);
}
}
}
// update the counter
var updateTime = 100;
function updateCounter(num) {
var len = num.length, lenC = getCommaSize(num);
var len2 = lastValueRev.length, lenC2 = getCommaSize(lastValueRev);
var reverse = reverseNum(num);
if (len < len2) { // need to shrink
for (var i = lenC2, ii = len2; i > lenC; i--) {
var img, j, k;
if (isCommaSpot(i)) {
img = null;
} else {
img = document.getElementById('ffNumber' + (ii - 1));
ii--;
}
for (var j = 0; j > -1; j -= 1/20) {
var k = i + j;
setTimeout((function(j, k, img) { return function() {
updateWidth(k);
if (img != null) {
var scaling = Math.max(0, 1 + j - 1/20);
img.style.MozOpacity = scaling;
img.style.width = Math.round(scaling * 10) + 'px';
with (img.nextSibling) {
if (className == 'comma') { // it's a comma
style.MozOpacity = scaling;
img.style.width = Math.round(scaling * 3) + 'px';
}
}
}
}; }) (j, k, img), (lenC2 - k) * updateTime);
}
setTimeout((function(img) { return function() {
if (img != null) {
img.src = images['blank'];
img.style.backgroundImage = 'url(' + images['blank'] + ')';
img.style.display = 'none';
with (img.nextSibling) {
if (className == 'comma') { // it's a comma
style.display = 'none';
}
}
}
}; }) (img), (lenC2 - i - j) * updateTime);
}
} else if (len > len2) { // need to grow
for (var i = lenC2, ii = len2; i < lenC; i++) {
var img, j, k;
if (isCommaSpot(i)) {
img = null;
} else {
img = document.getElementById('ffNumber' + (ii - 0));
if (img == null) { // need to make a new image
if (isCommaSpot(i+1)) { // new comma too
img = document.createElement('img');
img.className = 'comma';
img.src = images['comma'];
img.style.width = '0px';
img.style.position = 'relative';
img.style.left = '-1px';
img.style.display = 'none';
img.style.MozOpacity = 0;
with (document.getElementById('ffNumbers')) {
insertBefore(img, firstChild);
}
}
img = document.createElement('img');
img.id = 'ffNumber' + (ii - 0);
img.src = images['blank'];
img.style.width = '0px';
img.style.display = 'none';
img.style.MozOpacity = 0;
with (document.getElementById('ffNumbers')) {
insertBefore(img, firstChild);
}
}
ii++;
}
setTimeout((function(img) { return function() {
if (img != null) {
img.style.display = '';
with (img.nextSibling) {
if (className == 'comma') { // it's a comma
style.display = '';
}
}
}
}; }) (img), (i - lenC2) * updateTime);
for (var j = 0; j < 1; j += 1/20) {
var k = i + j;
setTimeout((function(j, k, img) { return function() {
updateWidth(k);
if (img != null) {
var scaling = Math.min(1, j + 1/20);
img.style.MozOpacity = scaling;
img.style.width = Math.round(scaling * 10) + 'px';
with (img.nextSibling) {
if (className == 'comma') { // it's a comma
style.MozOpacity = scaling;
style.width = Math.round(scaling * 3) + 'px';
}
}
}
}; }) (j, k, img), (k - lenC2) * updateTime);
}
}
}
// update the digits after the space has been prepared
for (var i = 0; i < len; i++) {
if (reverse[i] != lastValueRev[i]) {
setTimeout((function(i) { return function() {
shiftDigit('ffNumber' + i, reverse[i]);
}; }) (i), i * updateTime);
}
}
lastValueRev = reverse;
}
function updateWidth(lengthWithComma) {
document.getElementById('ffCounter').style.width = Math.round(10 + lengthWithComma * 8.234 + 31) + 'px'; // scale the size of the "background" image plus partial comma
}
function getCommaSize(num) {
return num.length + Math.floor((num.length - 1) / 3);
}
function isCommaSpot(num) {
return num % 4 == 0;
}
// digit shifting
var shiftRate = 1, shiftTime = 15, shiftAmount = 20; // 15 * 20 = 300 ms to update
function shiftDigit(id, num) {
with (document.getElementById(id)) {
style.backgroundImage = 'url(' + images[num] + ')'; // insert the new number
style.backgroundPosition = '0px ' + shiftAmount + 'px';
var i;
for (i = 0; i <= shiftAmount; i += shiftRate) {
setTimeout((function(i) { return function() {
style.backgroundPosition = '0px ' + Math.min(0, -shiftAmount + 1 + i) + 'px';
style.paddingTop = Math.min(shiftAmount, i) + 'px';
}; }) (i), i * shiftTime);
}
setTimeout(function() {
src = images[num]; // make the new number the actual image
style.paddingTop = '0px'; // shift it back to the original position
}, i * shiftTime);
}
}
// test cases
//prepCounter('50000000');
/*// shift it! with different sizes.. choppyish...
prepCounter('0');
setTimeout(function() { updateCounter('50123456'); }, 1000);
setTimeout(function() { updateCounter('546'); }, 2500);
setTimeout(function() { updateCounter('56105987'); }, 5000);
*/
/*// really really realllyy long number :o
prepCounter('12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890');
*/
/*// watch all 100 digits shift down! wheeee ;)
prepCounter('1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890');
for (var i = 0; i < 100; i++) {
setTimeout((function(i) { return function() { shiftDigit('ffNumber' + i, i % 10); }; }) (i), 100*i);
}
*/
// utility stuff
function intVal(str) {
str = '' + str;
if (str == '') return 0;
return str.match(/-?\d+/) - 0;
}
function reverseNum(num) {
return num.split('').reverse().join('');
}
function debug(out) {
with(document) {
body.appendChild(createTextNode(out));
body.appendChild(createElement('br'));
}
}
/* Slightly modified by Ed ;)
* ffcounter.js - A simple "odometer-style" counter for Firefox downloads.
*
* History:
* v0.1 - Initial version. Untested in IE. Inefficient handling of updates.
*
* Copyright 2005 Infocraft
* http://www.infocraft.com/
*
* The latest version of this script can be found at:
* http://www.infocraft.com/projects/ffcounter/ffcounter.js
*
* You may use this script in its entirety, modify it to suit your needs,
* adapt its functions, or just use it for inspiration. However, some form
* of acknowledgement, especially a link back to http://www.infocraft.com/, is
* always appreciated.
*/
/*************************** Adjustable Parameters ***************************/
var counter_url = "http://feeds.spreadfirefox.com/downloads/firefox.xml"; // The URL to your counter mirror.
var counter_id = "ffcounter"; // The id of the counter in your HTML.
var update_interval = 315; // The interval, in ms, to update the counter.
var resync_interval = 60000; // The interval, in ms, to resync with the feed.
/*************************** Static Globals ***************************/
var current_count = null;
var initial_count = null;
var initial_time = null;
var download_rate = null;
var request = null;
var counter_on = false;
/*************************** Public Functions ***************************/
// This should be called from your HTML, probably as an onload="get_count();"
// event in your tag.
function get_count()
{
var delay = (!initial_time || !initial_count) ? 10000 : resync_interval;
load_xml(counter_url);
// EDited to be a recursive call
if (!removed) {
setTimeout(function() { get_count(); }, delay);
}
}
/*************************** Private Functions ***************************/
// Adapted from the good people at ADC:
// http://developer.apple.com/internet/webcontent/xmlhttpreq.html
// this starts loading the XML data and sets up the process_request handler.
function load_xml(url)
{
/*// EDited: use greasemonkey instead
// branch for native XMLHttpRequest object
if (window.XMLHttpRequest) {
request = new XMLHttpRequest();
request.onreadystatechange = process_request;
request.open("GET", url, true);
request.send(null);
// branch for IE/Windows ActiveX version
} else if (window.ActiveXObject) {
request = new ActiveXObject("Microsoft.XMLHTTP");
if (request) {
request.onreadystatechange = process_request;
request.open("GET", url, true);
request.send();
}
}
*/
GM_xmlhttpRequest({
method: "GET",
url: url,
onload: function(details) { // just grab it when it finishes instead of readystate
request = details;
request.responseXML = (new DOMParser()).parseFromString(details.responseText, 'text/xml'); // greasemonkey doesn't provide responseXML
process_request();
}
});
}
// This function is called once the request state changes. It pulls the
// relevant data from the response and sends to update_count().
function process_request()
{
var response;
var time;
var count_item;
var count;
if (request.readyState == 4 && request.status == 200) {
response = request.responseXML;
time = response.getElementsByTagName('pubDate')[0].firstChild.data;
count_item = response.getElementsByTagName('item')[0];
count = count_item.getElementsByTagName('description')[0].firstChild.data;
update_count(time, count);
}
}
// Now that the data from the XML request has been extracted, this updates the
// global variables with that data.
function update_count(time, count)
{
if (!initial_count) {
initial_time = new Date(time);
initial_count = count.replace(/\D/g,'');
} else {
var last_time = new Date(time);
var last_count = count.replace(/\D/g,'');
download_rate = calculate_rate(last_time, last_count);
}
current_count = parseFloat(count.replace(/\D/g,''));
if (!counter_on) {
counter_on = true;
update_counter();
}
}
// Sticks the current download value into the DOM, and calls itself every
// update interval to increment the counter.
function update_counter()
{
// EDited: make counter calls instead of updating a html element
// var counter = document.getElementById(counter_id);
if (download_rate) {
current_count = current_count + download_rate;
updateCounter(format_count(current_count));
} else {
prepCounter(format_count(current_count));
download_rate = (3 + Math.random()) / 4; // just to get the counter moving, but this is pretty conservative
}
// counter.firstChild.data = format_count(current_count);
if (!removed) {
setTimeout(function() { update_counter(); }, update_interval);
}
}
/*************************** Utility Functions ***************************/
// Calculates the number of downloads per update interval.
function calculate_rate(last_time, last_count)
{
var time_delta = (last_time - initial_time) / update_interval;
var count_delta = (last_count - initial_count);
return count_delta / time_delta;
}
// Round off the current count and stick in commas where appropriate.
function format_count(count)
{
count = Math.round(count).toString();
// EDited: don't need commas.. just a string of numbers
// for (var i = count.length - 3; i > 0 ; i -= 3) {
// count = count.slice(0, i) + ',' + count.slice(i, count.length);
// }
return count;
}
get_count();
}, false);
}) ();