By recover
Has no other scripts.
// ==UserScript==
// @name Google Video Comments
// @namespace http://code.google.com/p/gvidcomments/
// @description Displays information about the comments your videos have received in your Google Video Status pages. If there are any new comments since your last check, it will notify you. Revision 25.
// @include http*://*google.tld/video/upload/Status*
// @include http*://*google.tld/video/upload/Stats*
// @include http*://upload.video.google.tld/Status*
// @include http*://upload.video.google.tld/Stats*
// ==/UserScript==
// Copyright (C) 2008 Stefan Sundin (recover89@gmail.com)
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// Documentation:
// Displays information about the comments your videos have received
// in your Google Video Status pages. If there are any new comments
// since your last check, it will notify you.
//
// Ideas for future revisions:
// * See http://code.google.com/p/gvidcomments/issues/list
function capitalize(str) {
return str.charAt(0).toUpperCase() + str.substr(1);
}
function closure(callback,arg1,arg2,arg3,arg4,arg5) {
if (arguments.length == 2) {
callback(arg1);
}
else if (arguments.length == 3) {
callback(arg1,arg2);
}
else if (arguments.length == 4) {
callback(arg1,arg2,arg3);
}
}
function clone(obj) {
var objectClone = new obj.constructor();
for (var property in obj) {
if (typeof obj[property] == 'object') {
objectClone[property] = clone(obj[property]);
}
else {
objectClone[property] = obj[property];
}
}
return objectClone;
}
function getFullMonth(date) {
var d=date.getMonth();
d++;
if (d <= 9) { return '0'+d; }
else { return d; }
}
function getFullDate(date) {
var d=date.getDate();
if (d <= 9) { return '0'+d; }
else { return d; }
}
function getFullHours(date) {
var d=date.getHours();
if (d <= 9) { return '0'+d; }
else { return d; }
}
function getFullMinutes(date) {
var d=date.getMinutes();
if (d <= 9) { return '0'+d; }
else { return d; }
}
function stopPropagation(e) {
e.stopPropagation();
}
//from json.org
json_fromString = function() {
var at,ch,escapee = {
'"': '"',
'\\': '\\',
'/': '/',
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
},text,error = function (m) {
throw {
name: 'SyntaxError',
message: m,
at: at,
text: text
};
},next = function (c) {
if (c && c !== ch) {
error("Expected '" + c + "' instead of '" + ch + "'");
}
ch = text.charAt(at);
at += 1;
return ch;
},number = function () {
var number,
string = '';
if (ch === '-') {
string = '-';
next('-');
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
if (ch === '.') {
string += '.';
while (next() && ch >= '0' && ch <= '9') {
string += ch;
}
}
if (ch === 'e' || ch === 'E') {
string += ch;
next();
if (ch === '-' || ch === '+') {
string += ch;
next();
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
}
number = +string;
if (isNaN(number)) {
error("Bad number");
} else {
return number;
}
},string = function () {
var hex,
i,
string = '',
uffff;
if (ch === '"') {
while (next()) {
if (ch === '"') {
next();
return string;
} else if (ch === '\\') {
next();
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(next(), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
string += String.fromCharCode(uffff);
} else if (typeof escapee[ch] === 'string') {
string += escapee[ch];
} else {
break;
}
} else {
string += ch;
}
}
}
error("Bad string");
},white = function () {
while (ch && ch <= ' ') {
next();
}
},word = function () {
switch (ch) {
case 't':
next('t');
next('r');
next('u');
next('e');
return true;
case 'f':
next('f');
next('a');
next('l');
next('s');
next('e');
return false;
case 'n':
next('n');
next('u');
next('l');
next('l');
return null;
}
error("Unexpected '" + ch + "'");
},value,array = function () {
var array = [];
if (ch === '[') {
next('[');
white();
if (ch === ']') {
next(']');
return array; // empty array
}
while (ch) {
array.push(value());
white();
if (ch === ']') {
next(']');
return array;
}
next(',');
white();
}
}
error("Bad array");
},object = function () {
var key,
object = {};
if (ch === '{') {
next('{');
white();
if (ch === '}') {
next('}');
return object;
}
while (ch) {
key = string();
white();
next(':');
object[key] = value();
white();
if (ch === '}') {
next('}');
return object;
}
next(',');
white();
}
}
error("Bad object");
};
value = function () {
white();
switch (ch) {
case '{':
return object();
case '[':
return array();
case '"':
return string();
case '-':
return number();
default:
return ch >= '0' && ch <= '9' ? number() : word();
}
};
return function (source, reviver) {
var result;
text = source;
at = 0;
ch = ' ';
result = value();
white();
if (ch) {
error("Syntax error");
}
return typeof reviver === 'function' ?
function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}({'': result}, '') : result;
};
}();
//from MDC
function json_toString(aJSObject, aKeysToDrop) {
var pieces = [];
function append_piece(aObj) {
if (typeof aObj == "string") {
aObj = aObj.replace(/[\\"\x00-\x1F\u0080-\uFFFF]/g, function($0) {
switch ($0) {
case "\b": return "\\b";
case "\t": return "\\t";
case "\n": return "\\n";
case "\f": return "\\f";
case "\r": return "\\r";
case '"': return '\\"';
case "\\": return "\\\\";
}
return "\\u" + ("0000" + $0.charCodeAt(0).toString(16)).slice(-4);
});
pieces.push('"' + aObj + '"')
}
else if (typeof aObj == "boolean") {
pieces.push(aObj ? "true" : "false");
}
else if (typeof aObj == "number" && isFinite(aObj)) {
pieces.push(aObj.toString());
}
else if (aObj === null) {
pieces.push("null");
}
else if (aObj instanceof Array ||
typeof aObj == "object" && "length" in aObj &&
(aObj.length === 0 || aObj[aObj.length - 1] !== undefined)) {
pieces.push("[");
for (var i = 0; i < aObj.length; i++) {
arguments.callee(aObj[i]);
pieces.push(",");
}
if (aObj.length > 0)
pieces.pop();
pieces.push("]");
}
else if (typeof aObj == "object") {
pieces.push("{");
for (var key in aObj) {
if (aKeysToDrop && aKeysToDrop.indexOf(key) != -1)
continue;
arguments.callee(key.toString());
pieces.push(":");
arguments.callee(aObj[key]);
pieces.push(",");
}
if (pieces[pieces.length - 1] == ",")
pieces.pop();
pieces.push("}");
}
else {
throw new TypeError("No JSON representation for this object!");
}
}
append_piece(aJSObject);
return pieces.join("");
}
//Data
var images={
x:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAALVBMVEUAABE9ZpFJb5dyjq7v8vZyjq/t8fXq7/NNcZhLcJihtcpzj6+kt8umuc3///+rkeKYAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXCRoTDABDjgGYAAAAP0lEQVQI12NgbhQUlDBgiKp79+75UgaVd0DgxCD3EASBlKAgiHonKPgOQUEFIUqgGvbkvXv37CoD80RBQUkDALGOI1+GXF1SAAAAAElFTkSuQmCC', //http://img0.gmodules.com/ig/images/skins/winterscape/common/x_blue.gif
x_highlight:'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAAIVBMVEUAACX///9Ca5VDa5ZZf6dYf6hDbJZZf6hagKlZgKg9ZpHHKAgpAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXCRoTDAqjW+iGAAAAPUlEQVQI12NgyVq1apkDQ9UqIFjOoAWiFjGsWii1UGoVkBIUBFGrBAVXISioIEQJVEMXiFrJwGq1atXiAADJ8SNFlwHa2wAAAABJRU5ErkJggg==', //http://img0.gmodules.com/ig/images/skins/winterscape/common/x_blue_highlight.gif
max: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAALVBMVEUAABE9ZpFJb5dyjq7v8vZyjq/t8fXq7/NNcZhLcJihtcpzj6+kt8umuc3///+rkeKYAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXChERLB6/IDHmAAAAO0lEQVQI12NgbhQUlDBgiKp79+75UgaVd0DgxCD37iEQwamHgoJyCApFDqphT967d8+uMjBPFBSUNAAAQqUm05WARH4AAAAASUVORK5CYII=', //http://img0.gmodules.com/ig/images/skins/winterscape/common/max_blue.gif
max_highlight: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAAIVBMVEUAACX///9Ca5VDa5ZZf6dYf6hDbJZZf6hagKlZgKg9ZpHHKAgpAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXChERLCUOK9jCAAAAOElEQVQI12NgyVq1apkDQ9UqIFjOoAWiFjGsWrVQatUqOLVQUFAKQaHIQTV0gaiVDKxWq1YtDgAALmglqdzTtMoAAAAASUVORK5CYII=', //http://img0.gmodules.com/ig/images/skins/winterscape/common/max_blue_highlight.gif
min: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAALVBMVEUAABE9ZpFJb5dyjq7v8vZyjq/t8fXq7/NNcZhLcJihtcpzj6+kt8umuc3///+rkeKYAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXChERMxnsHqrbAAAAOklEQVQI12NgbhQUlDBgiKp79+75UgaVd0DgxCAHoh7CqYeCgnIICkUOqmFP3rt3z64yME8UFJQ0AADSJypH3N2URAAAAABJRU5ErkJggg==', //http://img0.gmodules.com/ig/images/skins/winterscape/common/min_blue.gif
min_highlight: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAAIVBMVEUAACX///9Ca5VDa5ZZf6dYf6hDbJZZf6hagKlZgKg9ZpHHKAgpAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXChERMx3rc27CAAAANElEQVQI12NgyVq1apkDQ9UqIFjOoAWiFjGsAgM4tVBQUApBochBNXSBqJUMrFarVi0OAACRwigNX3OIHQAAAABJRU5ErkJggg==', //http://img0.gmodules.com/ig/images/skins/winterscape/common/min_blue_highlight.gif
update: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAAAXNSR0IArs4c6QAAAC1QTFRFAAAA////PWaRSW+Xco6u7/L2co6v7fH16u/zTXGYS3CYobXKc4+vpLfLprnN6jc8jAAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsbDxcQIE+0dwAAAD5JREFUCNdjYFmkpKTlwHC2UFBQ/BmDqSAQBDMoCgoBEZBSUgJRQkpKikIIQWQKqiG7UVBQYhsDyyQlJU0HAAO+C8zeBcuuAAAAAElFTkSuQmCC', //http://img0.gmodules.com/ig/images/skins/winterscape/common/arrow_blue.png
update_highlight: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAAAXNSR0IArs4c6QAAACFQTFRFAAAEPWaR////QmuVQ2uWWX+nWH+oQ2yWWX+oWoCpWYCo5G5hqwAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wsbDxYwAjql/gAAADpJREFUCNdjYHMUFBRJYJgoCARSDIYgSphBUFBIUVAQSCkpgSghJSVFQYQgMgXV0AiiJBhYCwUFxQMARBgHthtEeY8AAAAASUVORK5CYII=', //http://img0.gmodules.com/ig/images/skins/winterscape/common/arrow_blue_highlight.png
about: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMBAMAAACkW0HUAAAAAXNSR0IArs4c6QAAAC1QTFRFAAAAPWaRSW+Xco6u7/L2co6v7fH16u/zTXGYS3CYobXKc4+vpLfLprnN////RptuVQAAAAF0Uk5TAEDm2GYAAAABYktHRACIBR1IAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH1wwOExAgiQwztQAAAEVJREFUCNdjYG4UFJQwYIiqe/fu+VIGlXdA4MQg9xAEGeQEgQCDeigoCJJ7Jyj47iFQw0M5oIY9ee/ePbvKwDxRUFDSAADigx4xlksa7gAAAABJRU5ErkJggg==', //bitcons/heart.gif
about_highlight: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAHdElNRQfXDBYNIyIQfMajAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAa0lEQVQoz2P4//8/Q2T98v/OOdP+26ZNxIpBciA1ILVAxStwKkTHILUMTtlTidYAUsuALAADuPggzIAuiQsMgAZ8mrD6AZcmdHmswYpLMThYoxpWEh9xDcCIA0V3BDAGnbPxJA2gHEgNSC0A5PyKKqprvPoAAAAASUVORK5CYII=', //bitcons/heart.gif
arrow: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAMCAYAAABBV8wuAAAAB3RJTUUH1woFFw8tZa+b6wAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAC1JREFUGJVjYMAO/mMVBAEGZAwT/I9L8D8uwf+4BPFL4DQKr+VYnYvTg7iCBADthKdZsHJhYQAAAABJRU5ErkJggg==',
starLittle: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAJCAMAAAA8eE0hAAAAPFBMVEUAAADx59Ho17P/0wD/zgD/wwDawIb6ugHRsGjnqgXNqVnaoxfIoUrEmTvFlSq/kSvBjhvCiwu2gQ3u7u5vpfudAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXCgUXAAHQ7+vHAAAAPklEQVQIHQXBCQJAMAwAsFQxps79/68SUADiC4Bt30CvOvKo6sTVMrNdgbiXXO4BznmfTxDvsz7vgKkPo0/8SEMB0HwCA6EAAAAASUVORK5CYII=', //http://video.google.com/images/starLittle.gif
starLittleEmpty: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAJCAMAAAA8eE0hAAAAPFBMVEUAAADu7u7m6Ork5OTW2NrR0tLGx8q2triur7Kkpaabm56Vl5mSkpWIiYyHiIt/gIN/gIJ9foFtbnHu8PLzYnzdAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfXCgUWOzHLRl5kAAAAPklEQVQIHQXBCQJAMAwAsNScU4z+/68SkADa1wCO/QA986wzs9PutarWuyGeueYnwDXt0wXifbcxwNJD9IUfVM8B3pe248AAAAAASUVORK5CYII=', //http://video.google.com/images/starLittleEmpty.gif
starLittleHalf: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAJCAMAAAA8eE0hAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAABpUExURXh5fv////X19e7u7ujp7vLnz+Hh4t/c0+nWr//YAP/TAM3Nz//HANu+f/+9APG+A9OuYOqqA86mUN+iEMqeQJ2go8WVMMiTIJGTlZiRfsGNIMSLEMWIAIeJjL6CAX+AhX1/gnZ3fHN1eCQKyv8AAAABdFJOUwBA5thmAAAAAWJLR0QAiAUdSAAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9cLAhcaIxUVQfEAAABISURBVAgdBcGJAkJAFADA2fSKDhu20qHw/x9pBhQA8TsC3LoX6EsZ8n2aRuLZNjnt/wfE+5LTWoHHqUsziO/nuiwV1H3YjWc2i14DLH32UawAAAAASUVORK5CYII=', //http://video.google.com/images/starLittleHalf.gif
};
var gvidcomments_rev='25';
var defaultdata={
fullsize: false,
videos: {}
};
var data=eval(GM_getValue('data')) || clone(defaultdata);
var session={
openDocid: null,
openId: null,
numvideos: 0,
numcomments: 0,
newcomments: false,
loading: true,
error: false,
communityrating: {loading:true, error:false},
page: window.location.pathname.replace(/.*\//,''),
videos: {},
docids: []
};
function update() {
GM_log('Checking for updates to Google Video Comments. Current revision '+gvidcomments_rev+'.');
GM_xmlhttpRequest({
method:'GET',
url:'http://gvidcomments.googlecode.com/svn/trunk/gvidcomments-revision',
headers:{
'User-agent':'Mozilla/4.0 (compatible) Greasemonkey',
'Accept':'application/atom+xml,application/xml,text/xml'
},
onload:function(responseDetails) {
if (responseDetails.status == 200) {
if (responseDetails.responseText.replace(/\r|\n/g,'') != gvidcomments_rev) {
if (confirm('There is an update available!\nDo you want to install it?')) {
window.location.assign('http://gvidcomments.googlecode.com/svn/trunk/gvidcomments.user.js');
}
}
else {
alert('Nothing new :/');
}
} else {
var error='There was a problem checking for an update: '+responseDetails.status+' ('+responseDetails.statusText+')';
GM_log(error);
alert(error);
}
}
});
}
function about() {
alert('Google Video Comments - Revision '+gvidcomments_rev+'\nUserscript by recover89@gmail.com\nRead all about it at: http://code.google.com/p/gvidcomments/\n\nLicensed under GPL.');
}
function reset() {
if (confirm('Are you sure you want to reset all stored data?')) {
data=clone(defaultdata);
GM_setValue('data',uneval(data));
alert('Done. Refresh to see changes.');
}
}
function resize() {
var cp=document.getElementById('gvidcomments-commentspopup');
if (cp.style.display == 'block') {
var s=session.videos[session.openDocid];
var cb=document.getElementById('gvidcomments-commentsbox');
var arrow=document.getElementById('gvidcomments-arrow');
var commentTd=document.getElementById('gvidcomments-td-'+s.videoId);
//Reposition comments popup
cp.style.left=(commentTd.offsetParent.offsetLeft+commentTd.offsetLeft+commentTd.offsetWidth+8)+'px';
if (data.fullsize) {
cp.style.height=(window.innerHeight-10)+'px';
cp.style.width=(window.innerWidth-parseInt(cp.style.left)-20)+'px';
cb.style.height=(parseInt(cp.style.height)-cb.offsetTop-10)+'px';
}
//Reposition arrow image
arrow.style.left=(commentTd.offsetParent.offsetLeft+commentTd.offsetLeft+commentTd.offsetWidth+3)+'px';
arrow.style.top=(commentTd.offsetParent.offsetTop+commentTd.offsetTop+(commentTd.offsetHeight/2)-6)+'px';
}
}
function opencp(docid) {
//Set session
session.openDocid=docid;
var s=session.videos[docid];
session.openId=s.videoId;
//Get objects
var cp=document.getElementById('gvidcomments-commentspopup');
var cb=document.getElementById('gvidcomments-commentsbox');
var arrow=document.getElementById('gvidcomments-arrow');
var header=document.getElementById('gvidcomments-header');
var communityrating=document.getElementById('gvidcomments-communityrating');
var commentTd=document.getElementById('gvidcomments-td-'+s.videoId);
//Clear comments box
while (cb.hasChildNodes()) { cb.removeChild(cb.firstChild); }
//Hide comments box (avoid the tearing effect if its visible)
//Note: This prevents the comments box from scrolling to the top (bad)
//cp.style.display='none';
arrow.style.display='none';
//Reposition comments popup
//commentTd.offsetParent.offsetTop = the height from the top of the page to the table
//commentTd.offsetTop = the height from the top of the table to the column
cp.style.left=(commentTd.offsetParent.offsetLeft+commentTd.offsetLeft+commentTd.offsetWidth+8)+'px';
if (data.fullsize) {
cp.style.position='fixed';
cp.style.top='5px';
cp.style.height=(window.innerHeight-10)+'px';
cp.style.width=(window.innerWidth-parseInt(cp.style.left)-20)+'px';
}
else {
cp.style.position='absolute';
if (commentTd.offsetParent.offsetTop+commentTd.offsetTop-20 < window.pageYOffset) {
//This happens if the popup would stick up over the edge of the screen (so the top of it wouldn't normally be seen)
cp.style.top=(window.pageYOffset+5)+'px';
}
else if (commentTd.offsetParent.offsetTop+commentTd.offsetTop-20+parseInt(cp.style.height) > window.pageYOffset+window.innerHeight) {
//This happens if the popup would stick down below the screen contents (so the bottom of it wouldn't normally be seen)
cp.style.top=(window.pageYOffset+window.innerHeight-parseInt(cp.style.height)-5)+'px';
}
else {
//This happens if the popup will be entirely visibile in its normal position relative to the position of the column
cp.style.top=(commentTd.offsetParent.offsetTop+commentTd.offsetTop-20)+'px';
}
}
cp.style.display='block';
//Reposition arrow image
arrow.style.left=(commentTd.offsetParent.offsetLeft+commentTd.offsetLeft+commentTd.offsetWidth+3)+'px';
arrow.style.top=(commentTd.offsetParent.offsetTop+commentTd.offsetTop+(commentTd.offsetHeight/2)-6)+'px';
arrow.style.display='block';
//Edit header text
header.innerHTML=s.title;
header.title='docid: '+docid;
//Clear communityrating
while (communityrating.hasChildNodes()) { communityrating.removeChild(communityrating.firstChild); }
communityrating.title='';
//Put communityrating
if (session.communityrating.loading) {
communityrating.appendChild(document.createTextNode('Fetching ratings...'));
}
else if (session.communityrating.error) {
communityrating.appendChild(document.createTextNode('Error fetching ratings...'));
}
else {
//Get communityrating
var rating=s.communityrating.rating;
var numvotes=s.communityrating.numvotes;
//Put stars
for (var j=0; j < parseInt(rating); j++) {
var star=document.createElement('img');
star.src=images.starLittle;
star.alt='*';
communityrating.appendChild(star);
}
if (rating%1 > 0.25) {
var star=document.createElement('img');
star.src=images.starLittleHalf;
star.alt="'";
communityrating.appendChild(star);
j++;
}
for (; j < 5; j++) {
var star=document.createElement('img');
star.src=images.starLittleEmpty;
communityrating.appendChild(star);
}
//Put text
communityrating.title=rating;
communityrating.appendChild(document.createTextNode(' ('+numvotes+' rating'+(numvotes!=1?'s':'')+')'));
}
//Adjust the height of the comments box
cb.style.height=(parseInt(cp.style.height)-cb.offsetTop-10)+'px';
//Add the comments
if (s.failed) {
cb.appendChild(document.createTextNode(s.failed));
}
else if (session.error) {
cb.appendChild(document.createTextNode(session.error));
}
else if (session.loading) {
cb.appendChild(document.createTextNode('Loading comments...'));
}
else if (s.numcomments == 0) {
cb.appendChild(document.createTextNode('No comments'));
}
else {
s.comments.forEach(function(entry) {
//Add name
var b=document.createElement('b');
b.innerHTML=entry.name;
b.title=entry.id;
cb.appendChild(b);
//New comment?
if (s.newids.some(function(newid) {
if (newid == entry.id) {
return true;
}
})) {
var sup=document.createElement('sup');
sup.style.color='rgb(255,0,0)';
sup.appendChild(document.createTextNode(' new!'));
cb.appendChild(sup);
}
cb.appendChild(document.createElement('br'));
//Add date
var date=new Date(entry.date*1000);
var textdate=document.createElement('span');
textdate.style.color='rgb(0,128,0)';
textdate.appendChild(document.createTextNode(' '+capitalize(date.toLocaleFormat("%b %d, %Y"))));
textdate.title=date.toLocaleFormat("%Y-%m-%d %H:%M");
cb.appendChild(textdate);
//Add text
cb.appendChild(document.createElement('br'));
var text=document.createElement('span');
text.innerHTML=entry.text;
cb.appendChild(text);
//Add br
cb.appendChild(document.createElement('br'));
cb.appendChild(document.createElement('br'));
});
}
}
function closecp() {
//Set session
session.openDocid=null;
session.openId=null;
//Get objects
var cp=document.getElementById('gvidcomments-commentspopup');
var arrow=document.getElementById('gvidcomments-arrow');
//Hide
cp.style.display='none';
arrow.style.display='none';
}
function addclick(docid) {
var commentTd=document.getElementById('gvidcomments-td-'+session.videos[docid].videoId);
commentTd.addEventListener('click', function(){ closure(opencp,docid); }, false);
commentTd.addEventListener('click', stopPropagation, false);
}
(function() {
//Add menu commands
GM_registerMenuCommand('About gvidcomments',about);
GM_registerMenuCommand('Update gvidcomments',update);
GM_registerMenuCommand('Reset data',reset);
//Grab report table
var videoTable=document.getElementById('report');
if (session.page == 'Stats') {
videoTable.width=parseInt(videoTable.width)+100;
}
//Add comments header
var tableTitleTr=videoTable.getElementsByTagName('tr')[0];
var commentsTitle=document.createElement('td');
commentsTitle.id='gvidcomments-commentstitle';
if (session.page == 'Stats') {
commentsTitle.style.textAlign='right';
}
commentsTitle.style.cursor='pointer';
commentsTitle.title='About gvidcomments';
commentsTitle.addEventListener('click', about, false);
commentsTitle.appendChild(document.createTextNode('Comments'));
tableTitleTr.insertBefore(commentsTitle,tableTitleTr.getElementsByTagName('td')[3]);
//Add total footer
if (session.page == 'Stats') {
var tableFooterTr=videoTable.getElementsByTagName('tr')[videoTable.getElementsByTagName('tr').length-1];
var commentsTotal=document.createElement('td');
commentsTotal.id='gvidcomments-commentstotal';
commentsTotal.style.textAlign='right';
commentsTotal.appendChild(document.createTextNode('0'));
tableFooterTr.insertBefore(commentsTotal,tableFooterTr.getElementsByTagName('td')[3]);
}
//Create comments popup
var cp=document.createElement('div');
cp.id='gvidcomments-commentspopup';
cp.style.position='absolute';
cp.style.width='275px';
cp.style.height='420px';
cp.style.background='rgb(255,255,255)';
cp.style.border='1px solid rgb(0,0,0)';
cp.style.padding='5px';
cp.style.MozBorderRadius='10px';
cp.style.display='none';
document.body.appendChild(cp);
//Create arrow image
var arrow=document.createElement('img');
arrow.id='gvidcomments-arrow';
arrow.src=images.arrow;
arrow.style.position='absolute';
arrow.style.display='none';
document.body.appendChild(arrow);
//Make comments popup hide when clicking outside the popup
document.addEventListener('click', closecp, false);
cp.addEventListener('click', stopPropagation, false);
//Don't hide comments popup when clicking links outside the popup
var iterator=document.evaluate('//a', document, null, XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null);
var thisNode=iterator.iterateNext();
while (thisNode) {
thisNode.addEventListener('click', stopPropagation, false);
thisNode=iterator.iterateNext();
}
//Add close button to comments popup
var button=document.createElement('img');
button.title='Close';
button.src=images.x;
button.style.cssFloat='right';
button.style.marginRight='3px';
button.style.cursor='pointer';
button.addEventListener('mouseover', function(){ this.src=images.x_highlight; }, false);
button.addEventListener('mouseout', function(){ this.src=images.x; }, false);
button.addEventListener('click', closecp, false);
cp.appendChild(button);
//Add togglesize button to comments popup
var button=document.createElement('img');
button.title='Toggle size';
button.src=images[data.fullsize?'min':'max'];
button.style.cssFloat='right';
button.style.marginRight='3px';
button.style.cursor='pointer';
button.addEventListener('mouseover', function(){ this.src=images[(data.fullsize?'min':'max')+'_highlight']; }, false);
button.addEventListener('mouseout', function(){ this.src=images[data.fullsize?'min':'max']; }, false);
button.addEventListener('click', function(){
//Toggle
data.fullsize=data.fullsize?false:true;
GM_setValue('data',uneval(data));
this.src=images[data.fullsize?'min':'max'];
//Reposition
var s=session.videos[session.openDocid];
var commentTd=document.getElementById('gvidcomments-td-'+s.videoId);
if (data.fullsize) {
cp.style.position='fixed';
cp.style.top='5px';
cp.style.width=(window.innerWidth-parseInt(cp.style.left)-20)+'px';
cp.style.height=(window.innerHeight-10)+'px';
}
else {
cp.style.position='absolute';
cp.style.width='275px';
cp.style.height='420px';
if (commentTd.offsetParent.offsetTop+commentTd.offsetTop-20 < window.pageYOffset) {
cp.style.top=(window.pageYOffset+5)+'px';
}
else if (commentTd.offsetParent.offsetTop+commentTd.offsetTop-20+parseInt(cp.style.height) > window.pageYOffset+window.innerHeight) {
cp.style.top=(window.pageYOffset+window.innerHeight-parseInt(cp.style.height)-5)+'px';
}
else {
cp.style.top=(commentTd.offsetParent.offsetTop+commentTd.offsetTop-20)+'px';
}
}
cb.style.height=(parseInt(cp.style.height)-cb.offsetTop-10)+'px';
}, false);
cp.appendChild(button);
//Add update button to comments popup
var button=document.createElement('img');
button.title='Update gvidcomments';
button.src=images.update;
button.style.cssFloat='right';
button.style.marginRight='3px';
button.style.cursor='pointer';
button.addEventListener('mouseover', function(){ this.src=images.update_highlight; }, false);
button.addEventListener('mouseout', function(){ this.src=images.update; }, false);
button.addEventListener('click', update, false);
cp.appendChild(button);
//Add about button to comments popup
var button=document.createElement('img');
button.title='About gvidcomments';
button.src=images.about;
button.style.cssFloat='right';
button.style.marginRight='3px';
button.style.marginLeft='3px';
button.style.cursor='pointer';
button.addEventListener('mouseover', function(){ this.src=images.about_highlight; }, false);
button.addEventListener('mouseout', function(){ this.src=images.about; }, false);
button.addEventListener('click', about, false);
cp.appendChild(button);
//Add header text to comments popup
var header=document.createElement('b');
header.id='gvidcomments-header';
cp.appendChild(header);
cp.appendChild(document.createElement('br'));
//Add communityrating div to comments popup
var communityrating=document.createElement('div');
communityrating.id='gvidcomments-communityrating';
communityrating.style.color='grey';
communityrating.style.paddingBottom='5px';
cp.appendChild(communityrating);
//Add comments box to comments popup
var cb=document.createElement('div');
cb.id='gvidcomments-commentsbox';
cb.style.overflow='auto';
cb.style.paddingTop='5px';
cp.appendChild(cb);
//Detect window resizes
window.addEventListener('resize', resize, false);
//Detect keypress (j/k)
document.addEventListener('keypress', function(e){
var key=String.fromCharCode(e.charCode).toLowerCase();
var newId=0;
if (key == 'j') {
//Move down
if (session.openId == null) { newId=0; }
else if (session.openId+1 <= session.numvideos-1) { newId=session.openId+1; }
else { newId=0; }
opencp(session.docids[newId]);
}
else if (key == 'k') {
//Move up
if (session.openId == null) { newId=session.numvideos-1; }
else if (session.openId-1 >= 0) { newId=session.openId-1; }
else { newId=session.numvideos-1; }
opencp(session.docids[newId]);
}
}, false);
//Iterate videos
var videoId=0, videoTr;
while ((videoTr=document.getElementById(videoId+1)) !== null) {
//Another video
session.numvideos++;
//Start a session
var s={
videoId:videoId,
title:null,
ids:[],
previds:[],
newids:[],
numcomments:0,
communityrating:{},
newvideo:null,
failed:false,
comments:[]
};
//Add video comment cell
var commentTd=document.createElement('td');
commentTd.id='gvidcomments-td-'+videoId;
commentTd.title='Loading';
commentTd.vAlign='top';
if (session.page == 'Stats') {
commentTd.style.textAlign='right';
}
commentTd.appendChild(document.createTextNode('Loading'));
videoTr.insertBefore(commentTd,videoTr.getElementsByTagName('td')[3]);
//Do this video have a docid
var docid;
if (videoTr.getElementsByTagName('a').length == 0 || videoTr.getElementsByTagName('a')[0].href.indexOf('docid=') == -1) {
var error='This video is either processing, needs action, have been rejected or failed';
GM_log(error);
commentTd.title=error;
commentTd.removeChild(commentTd.firstChild);
commentTd.appendChild(document.createTextNode('Video not ready'));
//Set variables
s.failed='This video is either processing, needs action, have been rejected or failed (no docid could be found).';
s.communityrating.error=true;
docid=videoId.toString(); //Use videoId as docid since we can't find the real docid
s.title=videoTr.getElementsByTagName('td')[0].innerHTML;
}
else {
s.title=videoTr.getElementsByTagName('a')[0].innerHTML;
//Get the docid for this video
docid=videoTr.getElementsByTagName('a')[0].href;
docid=docid.substr(docid.indexOf('docid=')+'docid='.length);
if (docid.indexOf('&') != -1) { //remove &hl=en
docid=docid.substr(0,docid.indexOf('&'));
}
}
//Get possible previous information and add this video to the session
s.newvideo=(data.videos[docid] && data.videos[docid].ids?false:true);
session.videos[docid]=s;
if (!s.failed) {
//data.videos[docid]=data.videos[docid] || {ids:[]};
data.videos[docid]=data.videos[docid] || {};
}
session.docids.push(docid);
//Add mouse click (I couldn't get this to work without embedding it in a function, WEIRD!)
addclick(docid);
commentTd.style.cursor='pointer';
commentTd.style.color='rgb(0,50,250)';
videoId++;
}
//Get comments
var req={searchSpecs:[],applicationId:28};
session.docids.forEach(function(docid) {
req.searchSpecs.push({entities:[{url:'http://video.google.com/videoplay?docid='+docid}], groups:['public_comment'], matchExtraGroups:true, startIndex:0, numResults:100, includeNickNames:true});
});
/*var ta=document.createElement('textarea');
ta.value='req='+json_toString(req);
cp.appendChild(ta);*/
GM_xmlhttpRequest({
method:'POST',
url:'http://video.google.com/reviews/json/search',
headers:{
'User-agent':'Mozilla/4.0 (compatible) Greasemonkey',
'Accept':'application/atom+xml,application/xml,text/xml',
},
data:'req='+json_toString(req),
onload:function(responseDetails) {
if (responseDetails.status == 200) {
/*var ta=document.createElement('textarea');
ta.value=responseDetails.responseText;
cp.appendChild(ta);*/
var comments=json_fromString(responseDetails.responseText);
if (!comments.channelHeader.errorCode) {
comments.searchResults.forEach(function(searchResult) {
//Iterate comments
if (searchResult.annotations) {
//Get docid
var docid=searchResult.annotations[0].entity.url;
docid=docid.substr(docid.indexOf('docid=')+'docid='.length);
//Set crispy shortcut
var s=session.videos[docid];
//Count the number of comments
s.numcomments=searchResult.numAnnotations;
session.numcomments+=s.numcomments;
//Iterate comments
searchResult.annotations.forEach(function(annotation) {
//Get entry
var entry={
name: (annotation.entity.nickname?annotation.entity.nickname:'(anonymous)'),
date: annotation.timestamp,
text: annotation.comment,
id: annotation.entity.groups[1] };
//Store
s.comments.push(entry);
s.ids.push(parseInt(entry.id));
});
//Check if I have the ids of the comments stored from a previous check
if (s.newvideo) {
data.videos[docid].ids=s.ids;
}
s.previds=data.videos[docid].ids.slice();
//Check which comments are new
s.ids.map(function(id) {
if (!s.previds.some(function(previd) {
if (id == previd) {
return true;
}
})) {
s.newids.push(id);
}
});
}
});
}
else {
session.error='Failed to fetch comments. Error code: '+comments.channelHeader.errorCode;
GM_log(session.error);
}
}
else {
session.error='Failed to fetch comments. HTTP response: '+responseDetails.status;
GM_log(session.error);
}
session.loading=false;
//Put numcomments
session.docids.forEach(function(docid) {
var s=session.videos[docid];
var commentTd=document.getElementById('gvidcomments-td-'+s.videoId);
commentTd.removeChild(commentTd.firstChild);
if (session.error) {
commentTd.appendChild(document.createTextNode('Error'));
commentTd.title=session.error;
}
else {
commentTd.appendChild(document.createTextNode(s.numcomments+(session.page=='Status'?' comment'+(s.numcomments!=1?'s':''):'')));
commentTd.title='Click to view comments';
//Are there any new comments on this video?
if (s.newids.length != 0) {
session.newcomments=true;
//Put 'new!' text
var sup=document.createElement('sup');
sup.style.color='rgb(255,0,0)';
sup.appendChild(document.createTextNode(' new!'));
commentTd.appendChild(sup);
//Add the new ids to the stored ids
data.videos[docid].ids=s.newids.concat(data.videos[docid].ids); //Appending previds to newids will put the ids in the order they appear when fetching them
}
//Refresh cp?
if (session.openDocid == docid) {
opencp(docid);
}
}
});
//Put session.numcomments
if (session.page == 'Status') {
commentsTitle.title=session.numcomments+' comments on this page';
}
else if (session.page == 'Stats') {
commentsTotal.removeChild(commentsTotal.firstChild);
commentsTotal.appendChild(document.createTextNode(session.numcomments));
commentsTotal.title='Average number of comments per video: '+Math.round(session.numcomments/session.numvideos);
}
//Add new text to comment header?
if (session.newcomments) {
var sup=document.createElement('sup');
sup.style.color='rgb(255,0,0)';
sup.appendChild(document.createTextNode(' new!'));
commentsTitle.appendChild(sup);
}
//Save
GM_setValue('data',uneval(data));
}
});
//Get communityrating
var req={entities:[],includeAggregateInfo:true,applicationId:28};
session.docids.forEach(function(docid) {
req.entities.push({url:'http://video.google.com/videoplay?docid='+docid});
});
/*var ta=document.createElement('textarea');
ta.value='req='+json_toString(req);
cp.appendChild(ta);*/
GM_xmlhttpRequest({
method:'POST',
url:'http://video.google.com/reviews/json/lookup',
headers:{
'User-agent':'Mozilla/4.0 (compatible) Greasemonkey',
'Accept':'application/atom+xml,application/xml,text/xml',
},
data:'req='+json_toString(req),
onload:function(responseDetails) {
if (responseDetails.status == 200) {
/*var ta=document.createElement('textarea');
ta.value=responseDetails.responseText;
cp.appendChild(ta);*/
var ratings=json_fromString(responseDetails.responseText);
ratings.annotations.forEach(function(entry) {
//Get docid
var docid=entry.entity.url;
docid=docid.substr(docid.indexOf('docid=')+'docid='.length);
//Get data
var rating=entry.aggregateInfo.averageRating;
var numvotes=0;
entry.aggregateInfo.starRatings.forEach(function(starRating) {
numvotes+=starRating.count;
});
//Set crispy shortcut
var s=session.videos[docid];
//Set communityrating
s.communityrating.rating=rating;
s.communityrating.numvotes=numvotes;
});
//Refresh cp?
if (session.openDocid == docid) {
opencp(docid);
}
}
else {
session.communityrating.error=true;
}
session.communityrating.loading=false;
}
});
})();