/*******************************************************************************
********************************************************************************
*** ** ****** ****** ********
**** ** ** ** ** ** ** **
** ** ** ** ** ** ** ** **
** ** ** ** ** ** ** *******
** ** ** ** ** ** ** ** **
** ** ** ** ** ** ** ** **
** **** ** ** ** ** ** **
** *** ****** ****** ********
********************************************************************************
*****************It isn't an acronym. Caps lock broke.**************************
********************************************************************************
This gadget was developed by the Grouplens Research lab (http://grouplens.org)
to be used in the English Wikipedia. See
http://en.wikipedia.org/wiki/User:EpochFail/NOOB for documentation and
installation instructions. Any questions or concerns should be directed to
User:EpochFail.
*******************************************************************************/
if(!NOOB){
var NOOB = {}
}
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
results = regex.exec(location.search);
return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
NOOB.DateDiffer = {
second: 1000,
minute: 1000 * 60,
hour: 1000 * 60 * 60,
day: 1000 * 60 * 60 * 24,
week: 1000 * 60 * 60 * 24 * 7,
month: 1000 * 60 * 60 * 24 * 30.44,
year: 1000 * 60 * 60 * 24 * 365.242,
approxDiff: function(date1, date2){
var dateDiffMS = date1-date2
diff = {}
diff.years = Math.floor(dateDiffMS/this.year)
dateDiffMS -= diff.years*this.year
diff.months = Math.floor(dateDiffMS/this.month)
dateDiffMS -= diff.months*this.month
diff.weeks = Math.floor(dateDiffMS/this.week)
dateDiffMS -= diff.weeks*this.week
diff.days= Math.floor(dateDiffMS/this.day)
dateDiffMS -= diff.days*this.day
diff.hours = Math.floor(dateDiffMS/this.hour)
dateDiffMS -= diff.hours*this.hour
diff.minutes = Math.floor(dateDiffMS/this.minute)
dateDiffMS -= diff.minutes*this.minute
diff.seconds = Math.floor(dateDiffMS/this.second)
dateDiffMS -= diff.seconds*this.second
diff.milliseconds = Math.floor(dateDiffMS)
return diff
},
human: function(diff){
var timeString = ""
if(diff.years > 0){
timeString += diff.years + " year"
if(diff.years > 1){
timeString += "s"
}
timeString += " and " + diff.months + " month"
if(diff.months > 1){
timeString += "s"
}
}else if(diff.months > 0){
timeString += diff.months + "month"
if(diff.months > 1){
timeString += "s"
}
timeString += " and " + diff.weeks*7+diff.days + " day"
if(diff.weeks*7+diff.days > 1){
timeString += "s"
}
}else if(diff.weeks > 0){
timeString += diff.weeks + "week"
if(diff.weeks > 1){
timeString += "s"
}
timeString += " and " + diff.days + " day"
if(diff.days > 1){
timeString += "s"
}
}else if(diff.days > 0){
timeString += diff.days + "day"
if(diff.days > 1){
timeString += "s"
}
timeString += " and " + diff.hours + " hour"
if(diff.hours > 1){
timeString += "s"
}
}else if(diff.hours > 0){
timeString += diff.hours + "hour"
if(diff.hours > 1){
timeString += "s"
}
timeString += " and " + diff.minutes + " minute"
if(diff.minutes > 1){
timeString += "s"
}
}else if(diff.minutes > 0){
timeString += diff.minutes + "minute"
if(diff.minutes > 1){
timeString += "s"
}
timeString += " and " + diff.seconds + " second"
if(diff.seconds > 1){
timeString += "s"
}
}else{
timeString += diff.seconds + "second"
if(diff.seconds > 1){
timeString += "s"
}
timeString += " and " + diff.milliseconds + " ms"
}
return timeString
}
}
if(!NOOB){
var NOOB = {}
}
NOOB.Editor = function(username){
this.username = username
this.links = []
this.signatures = []
}
NOOB.Editor.prototype.addLink = function(link){
this.links.push(link)
}
NOOB.Editor.prototype.addSignature = function(signature){
this.signatures.push(signature)
}
NOOB.Editor.prototype.updateEditCount = function(user){
if(user.registration){
var dateParts = user.registration.match(/([0-9]{4})-([0-1][0-9])-([0-3][0-9])T([0-9]{2}):([0-9]{2}):([0-9]{2})Z/)
var regDate = new Date(dateParts[1], dateParts[2], dateParts[3], dateParts[4], dateParts[5], dateParts[6])
var nowDate = new Date()
var diff = NOOB.DateDiffer.approxDiff(nowDate, regDate)
var diffString = NOOB.DateDiffer.human(diff)
}else{
var diffString = " an unknown amount of time"
}
var className = ""
if(user.editcount < 10){
className = "ten_1"
}else if(user.editcount < 100){
className = "ten_2"
}else if(user.editcount < 1000){
className = "ten_3"
}else if(user.editcount < 10000){
className = "ten_4"
}else{
className = "ten_5"
}
for(var i=0;i<this.links.length;i++){
var link = this.links[i]
link.update(className, user.editcount, diffString)
}
for(var i=0;i<this.signatures.length;i++){
var signature = this.signatures[i]
signature.update(className, user.editcount, diffString)
}
}
NOOB.Editor.prototype.setUnknown = function(){
for(var i=0;i<this.links.length;i++){
var link = this.links[i]
link.unknown()
}
for(var i=0;i<this.signatures.length;i++){
var signature = this.signatures[i]
signature.unknown()
}
}
if(!NOOB){
var NOOB = {}
}
NOOB.Signature = function(userHref, spanNode){
this.expressions = []
this.expressions.push(/\/wiki\/(U|u)ser(_talk)?:([^\/#]+)/)
this.expressions.push(/\/wiki\/(S|s)pecial:(C|c)ontributions\/([^\/#]+)/)
this.expressions.push(/\/w\/index\.php\?title=User_talk:([^\/#]+)&action=edit&redlink=1/)
this.expressions.push(/\/wiki\/(S|s)pecial:(E|e)mailUser\/([^\/#]+)/)
if(userHref){
for(var i=0;i<this.expressions.length && !this.username;i++){
var expression = this.expressions[i]
match = userHref.match(expression)
if(match != null){
this.username = match[match.length-1]
}
}
}
if(!this.username){
this.username = "?unknown?"
}
this.spanNode = spanNode
}
NOOB.Signature.prototype.update = function(className, editCount, diffString){
this.spanNode.removeClass('loading')
this.spanNode.addClass(className)
this.spanNode.html('<a href="/wiki/Special:Contributions/' + this.username + '">hist</a>')
this.spanNode.attr('title', editCount + " revisions in " + diffString)
}
NOOB.Signature.prototype.unknown = function(){
this.spanNode.removeClass('loading')
this.spanNode.addClass('unknown')
this.spanNode.html('<a href="/wiki/Special:Contributions/' + this.username + '">?</a>')
}
if(!NOOB){
var NOOB = {}
}
NOOB.Link = function(editorLink){
this.username = editorLink.text().replace(/ /g, "_")
this.link = editorLink
}
NOOB.Link.prototype.update = function(className, editCount, diffString){
this.link.attr("title", user.editcount + " revisions in " + diffString)
$(' <span class="contribs ' + className + '" title="' + user.editcount + " revisions in " + diffString + '"> </span> ').insertBefore(this.link)
}
NOOB.Link.prototype.unknown = function(){
$(' <span class="contribs unknown" title="unknown">?</span> ').insertBefore(this.link)
}
if(!NOOB){
var NOOB = {}
}
NOOB.Editors = function(){
this.editors = {}
}
NOOB.Editors.prototype.addEditorLink = function(editorLink){
var link = new NOOB.Link(editorLink)
if(this.editors[link.username] == undefined){
this.editors[link.username] = new NOOB.Editor(link.username)
}
this.editors[link.username].addLink(link)
}
NOOB.Editors.prototype.addEditorSignature = function(href, spanNode){
var signature = new NOOB.Signature(href, spanNode)
if(this.editors[signature.username] == undefined){
this.editors[signature.username] = new NOOB.Editor(signature.username)
}
this.editors[signature.username].addSignature(signature)
}
NOOB.Editors.prototype.loadEditCount = function(){
var usernames = []
for(var username in this.editors){
usernames.push(username)
}
var params = {
"action": 'query',
"list": 'users',
"ususers": usernames.join("|"),
"usprop": 'editcount|registration',
"format": 'json'
}
NOOB.WPAPIHandler.performGET(
params,
function(res, args){
try{
var users = res.query.users
}
catch(e){
alert("Invalid result structure")
return
}
for(var i=0;i<users.length;i++){
user = users[i]
if(user.editcount != undefined){
user.hrefName = user.name.replace(/ /g, "_")
try{
args.self.editors[user.hrefName].updateEditCount(user)
}catch(e){
alert(user.hrefName)
}
}else{
user.hrefName = user.name.replace(/ /g, "_")
args.self.editors[user.hrefName].setUnknown()
}
}
},
{self: this},
function(message){
alert(message)
}
)
}
if(!NOOB){
var NOOB = {}
}
/**
* Wikipedia API Handler
*
* A simple object for interacting with Wikipedia's API.
*/
NOOB.WPAPIHandler=function(){};NOOB.WPAPIHandler.timeoutSeconds=25;if(mw.config.get('wgServer')&&wgScriptPath){NOOB.WPAPIHandler.url=mw.config.get('wgServer')+mw.config.get('wgScriptPath')+"/api.php"}else{NOOB.WPAPIHandler.url="http://en.wikipedia.org/w/api.php"}NOOB.WPAPIHandler.performGET=function(d,b,a,c){this.performRequest(d,b,a,c,"GET")};NOOB.WPAPIHandler.performPOST=function(d,b,a,c){this.performRequest(d,b,a,c,"POST")};NOOB.WPAPIHandler.performRequest=function(f,b,a,e,d){var c=function(g,h){if(h=="success"){b(g,a)}else{e(h)}};if(d=="POST"){$.post(this.url,f,c,"json")}else{$.get(this.url,f,c,"json")}};NOOB.WPAPIHandler.objectToString=function(c,b){b=b||0;str="";for(thing in c){for(var a=0;a<b;a++){str+=" "}if(typeof(c[thing])=="object"){str+=thing+": \n"+NOOB.WPAPIHandler.objectToString(c[thing],b+1)}else{str+=thing+": `"+c[thing]+"`\n"}}return str};
NOOB.getPrecedingAnchor = function(nodeList, i){
for(var j=i;j>0;j--){
node = nodeList[j]
if(node.constructor){
if(node.constructor == HTMLAnchorElement){
return node
}
else{
lastAnchor = $('a:last', node)
if(lastAnchor.length > 0){
return lastAnchor
}
}
}
}
return null
}
NOOB.getSignatures = function(){
var signatureNodes = []
//First process the autosigned comments (because it is easiest)
var autoSigned = $('.autosigned:not(p > small > .autosigned)')
for(var i=0;i<autoSigned.length;i++){
var sigElement = $(autoSigned.get(i))
var lastAnchor = $('a:last', sigElement)
var signature = {href:lastAnchor.attr('href'), spanNode:$('<span class="signature loading"></span>')}
signatureNodes.push(signature)
signature.spanNode.insertAfter(sigElement)
}
//Next process all first-level comments
var pTags = $('#contentSub ~ p')
for(var i=0;i<pTags.length;i++){
var textBlock = $(pTags.get(i))
if(textBlock.text().match(/[0-9]{2}:[0-9]{2}, [0-9]{1,2} (January|Febuary|March|April|May|June|July|August|September|October|November|December) (1|2)[0-9]{3} \(UTC\)$/g) != null){
var lastAnchor = $('a:last', textBlock)
var signature = {href:lastAnchor.attr('href'), spanNode:$('<span class="signature loading"></span>')}
signatureNodes.push(signature)
textBlock.append(signature.spanNode)
}
}
//Finally, process all nested comments
var definitionLists = $('#contentSub ~ dl')
for(var k=0;k<definitionLists.length;k++){
var definitions = $('dd', definitionLists.get(k))
for(var i=0;i<definitions.length;i++){
var definition = definitions.get(i)
for(var j=0;j<definition.childNodes.length;j++){
var node = definition.childNodes[j]
if(node.constructor && node.constructor == Text){
if(node.textContent.match(/[0-9]{2}:[0-9]{2}, [0-9]{1,2} (January|Febuary|March|April|May|June|July|August|September|October|November|December) (1|2)[0-9]{3} \(UTC\)(\n)?$/g) != null){
var precedingAnchor = this.getPrecedingAnchor(definition.childNodes, j)
if(precedingAnchor){
precedingAnchor = $(precedingAnchor)
var signature = {href:precedingAnchor.attr('href'), spanNode:$('<span class="signature loading"></span>')}
signatureNodes.push(signature)
if(definition.childNodes.length > j+1){
definition.insertBefore(signature.spanNode[0], definition.childNodes[j+1])
}else{
definition.appendChild(signature.spanNode[0])
}
}
}
}
}
}
}
return signatureNodes
}
if(getParameterByName("action") == "history"){
importStylesheet("User:EpochFail/NOOB.css")
NOOB.editors= new NOOB.Editors()
$(document).ready(function(){
var editorLinks = $('.mw-userlink')
for(var i=0;i<editorLinks.length;i++){
var editorLink = $(editorLinks[i])
NOOB.editors.addEditorLink(editorLink)
}
NOOB.editors.loadEditCount()
})
}else{
if(getParameterByName("title") != ''){
var title = getParameterByName("title")
}else{
matches = window.location.href.match(/https?:\/\/[a-z]{2}\.wikipedia\.org\/wiki\/(.+)/)
if(matches != null){
var title = matches[1]
}else{
var title = ""
}
}
var namespace = title.split(":", 1)[0]
title = title.substring(namespace.length+1)
if(namespace.match(/(((T|t)alk)|(((U|u)ser)|((W|w)ikipedia)|((I|i)mage)|((M|m)ediaWiki)|((T|t)emplate)|((H|h)elp)|((C|c)ategory)|((P|p)ortal))(_| )talk)/) != null){
//We know we are on a talk page! Let's look for signiatures
importStylesheet("User:EpochFail/NOOB.css")
//importStylesheetURI('http://wikipedia.grouplens.org/NOOB/css/NOOB.css')
NOOB.editors = new NOOB.Editors()
$(document).ready(function(){
var signatureNodes = NOOB.getSignatures()
for(var i=0;i<signatureNodes.length;i++){
sigNode = signatureNodes[i]
NOOB.editors.addEditorSignature(sigNode.href, sigNode.spanNode)
}
NOOB.editors.loadEditCount()
})
}
}