User:Bradv/sprint.js

sprint = {

enabled: false,

paused: false,

portlets: [

{ id: 'wl', enabled: true, items: 10, refresh: 5 },

{ id: 'np', enabled: true, items: 10, refresh: 5 },

{ id: 'onp', enabled: true, items: 10, refresh: 5 },

{ id: 'rc', enabled: true, items: 10, refresh: 5 }

],

ajax: [],

ajaxPreview: null

};

sprint.modules = [

{ id: 'wl',

type: 'query',

title: 'Watchlist',

url: "/w/api.php?format=xml&action=query&list=watchlist&wllimit=",

tag: 'item',

titlelink:'/wiki/Special:Watchlist'},

{ id: 'np',

type: 'query',

title: 'New Pages',

url: "/w/api.php?action=query&format=xml&list=recentchanges&rcshow=!bot|!redirect&rctype=new&rcnamespace=0&rcprop=title|timestamp|ids|patrolled&rclimit=",

tag: 'rc',

titlelink:'/wiki/Special:NewPages'},

{ id: 'onp',

type: 'query',

title: 'Oldest Unpatrolled',

url: "/w/api.php?action=query&format=xml&list=recentchanges&rcshow=!bot|!redirect|!patrolled&rctype=new&rcnamespace=0&rcprop=title|timestamp|ids|patrolled&rcdir=newer&rclimit=",

tag: 'rc',

titlelink:'/w/index.php?title=Special:NewPages&dir=prev&hidepatrolled=1' },

{ id: 'rc',

type: 'query',

title: 'Recent Changes',

url: "/w/api.php?format=xml&action=query&list=recentchanges&rclimit=",

tag: 'rc',

titlelink:'/w/index.php?title=Special:RecentChanges&limit=50&hideliu=1' }

];

m_zIndex=101;

sprint.loadCookies=function() {

sprint.enabled = (sprint.readCookie('sprint_enabled')=='true');

var cookie = sprint.readCookie('sprint_portlets');

if (cookie) {

sprint.portlets = [];

var arrPortlets = cookie.split('||');

for (var i=0; i

sprint.portlets[i]={};

var s = arrPortlets[i].split('|');

sprint.portlets[i].id = s[0];

sprint.portlets[i].enabled = (s[1]=='true');

sprint.portlets[i].items = s[2];

sprint.portlets[i].refresh = s[3];

}

}

for (var i=0; i

var p = sprint.portlets[i];

for (var j=0; j

var m = sprint.modules[j];

if (p.id==m.id) {

p.module = m;

}

}

}

};

sprint.saveCookies=function() {

var cend = "; expires=Tue, 31-Dec-2030 23:59:59 GMT; path=/";

document.cookie = 'sprint_enabled=' + sprint.enabled.toString() + cend;

var arr = [];

for (var i=0; i

var p = sprint.portlets[i];

arr[i] = p.id + '|' + p.enabled.toString() + '|' + p.items + '|' + p.refresh;

}

document.cookie = 'sprint_portlets='+arr.join('||')+cend;

};

sprint.pause = function () {

sprint.paused=true;

p = document.getElementById('sprint_ovl');

if (p) {

p.style.display='';

}

};

sprint.refresh = function () {

if(sprint.paused) {

sprint.paused=false;

p = document.getElementById('sprint_ovl');

if (p) {

p.style.display='none';

}

sprint.loadCookies();

sprint.drawSprint();

}

};

sprint.init = function () {

sprint.loadCookies();

mw.util.addPortletLink ('p-personal', '#', 'My Sidebar', 'toggleSprint');

document.getElementById('toggleSprint').setAttribute('onclick', 'sprint.toggleSprint();return false;');

sprint.drawSprint();

window.onblur = sprint.pause;

window.onfocus = sprint.refresh;

importStylesheetURI('/skins-1.5/common/diff.css');

};

sprint.drawSprint=function() {

sb = document.getElementById('sprint');

if (sprint.enabled) {

if (sb) {

sb.style.display='';

} else {

//Create the main sprint bar

sb = document.createElement('div');

sb.id='sprint';

sb.className='portlet';

sb.style.width='12em';

sb.style.top='0px';

sb.style.right='0px';

sb.style.bottom='0px';

sb.style.zIndex=90;

sb.style.margin='0';//'.1em';

sb.style.padding='.5em';

sb.style.position='absolute';

sb.style.borderLeft='1px solid #bbbbbb;';

sb.style.backgroundColor=document.defaultView.getComputedStyle(document.body, null).backgroundColor;

sb.style.position='fixed';

//Find the container where the sprint bar goes.

//This differs between monobook and modern skins.

container = document.getElementById('content');

if (!container) {

container = document.getElementById('mw_content');

}

container.appendChild(sb);

//Create the overlay for when it is paused (out of focus)

ovl = document.createElement('div');

ovl.id='sprint_ovl';

ovl.style.position='absolute';

ovl.style.top='0px';

ovl.style.right='0px';

ovl.style.width='100%';

ovl.style.height='100%';

ovl.style.borderLeft='1px solid #bbbbbb;';

ovl.style.backgroundColor=document.defaultView.getComputedStyle(document.body, null).backgroundColor;

ovl.zIndex=100;

ovl.style.display='none';

p = document.createElement('p');

p.style.position='absolute';

p.style.top='5em';

p.style.width='100%';

p.style.fontSize='1em';

p.style.lineHeight='2em';

p.style.textAlign='center';

p.style.color='#bbbbbb';

p.appendChild(document.createTextNode('Updates paused'));

p.appendChild(document.createElement('br'));

p.appendChild(document.createTextNode('Click to resume'));

ovl.appendChild(p);

sb.appendChild(ovl);

}

//Set the spacer between the main body and the Sprint sidebar

var spacer = (sb.offsetWidth)+'px';

topbar = document.evaluate('//div[@id="p-personal"]//div[@class="pBody"]',

document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

if (topbar.singleNodeValue) {

topbar.singleNodeValue.style.marginRight=spacer;

}

sb.parentNode.style.marginRight=spacer;

//Draw the portlets

for (var i=0; i

sprint.drawPortlet(i);

}

} else { //Hide the sprint bar, if it has already been drawn

topbar = document.evaluate('//div[@id="p-personal"]//div[@class="pBody"]',

document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);

if (topbar.singleNodeValue) {

topbar.singleNodeValue.style.marginRight='';

}

if (sb) {

sb.parentNode.style.marginRight='';

sb.style.display='none';

}

}

};

//Draw each of the portlets. Called by drawSprint()

sprint.drawPortlet=function(index) {

if (!sprint.enabled || sprint.paused) return false;

var ptl = sprint.portlets[index];

sprint.makePortlet(ptl.module.title, ptl.module.titlelink, 'p-sb'+index, ptl.enabled, 'sprint.toggle('+index+')');

if (ptl.enabled) {

if (!sprint.ajax) {

sprint.ajax = [];

}

sprint.ajax[index] = sajax_init_object();

if (sprint.ajax[index]) {

sprint.ajax[index].onreadystatechange = function() {

if(sprint.ajax[index].readyState == 4) {sprint.portletCallback(index);}

};

url = ptl.module.url + ptl.items;

sprint.ajax[index].open("GET", url, true);

sprint.ajax[index].send(null);

} else {

pBody = document.getElementById('p-sb'+index);

while (pBody.firstChild) {

pBody.removeChild(pBody.firstChild);

}

}

}

};

sprint.portletCallback=function(index) {

var url = sprint.portlets[index].module.url;

var tag = sprint.portlets[index].module.tag;

var items;

try {

items = sprint.ajax[index].responseXML.documentElement.getElementsByTagName(tag);

} catch (e) {

setTimeout('sprint.drawPortlet('+index+')', sprint.portlets[index].refresh * 1000);

return;

}

pBody = document.getElementById('p-sb'+index);

while (pBody.firstChild) {

pBody.removeChild(pBody.firstChild);

}

var patrol = (url.indexOf('patrolled')>=0);

for (var i=0; i

var title = items[i].getAttribute('title');

var rcid = items[i].getAttribute('rcid');

var revid = items[i].getAttribute('revid');

var type = items[i].getAttribute('type');

var item_url;

var not_patrolled=false;

if (type=='new') {

if (patrol) not_patrolled = (items[i].getAttribute('patrolled')==null);

item_url = mw.config.get('wgScript') + '?title=' + title.replace(' ', '_', "g").replace('&', '%26', "g") + '&rcid=' + rcid;//+ '&redirect=no'; (this screws up Friendly)

} else {

item_url = mw.config.get('wgScript') + '?title=' + title.replace(' ', '_', "g").replace('&', '%26', "g") + '&oldid=' + revid;

}

var a = document.createElement('a');

a.setAttribute('nopopup', 'true'); //TODO: Test interaction with popups

a.href=item_url;

a.title=title;

a.appendChild(document.createTextNode(title));

var p = sprint.createLine(pBody);

p.appendChild(a);

p.appendChild(document.createTextNode(' ['));

pre = document.createElement('a');

pre.setAttribute('nopopup', 'true');

pre.setAttribute('href', '#');

pre.setAttribute('onclick', 'sprint.showPreview("'+title+'", "'+item_url+'&diff=prev&action=render");return false;');

pre.appendChild(document.createTextNode('preview'));

p.appendChild(pre);

p.appendChild(document.createTextNode(']'));

if (not_patrolled) {

p.style.fontWeight='bold';

p.appendChild(document.createTextNode(' ['));

ap = document.createElement('a');

ap.setAttribute('nopopup', 'true');

ap.setAttribute('href', '#');

ap.setAttribute('onclick', 'sprint.patrol("'+item_url+'&action=markpatrolled");return false;');

ap.appendChild(document.createTextNode('patrol'));

p.appendChild(ap);

p.appendChild(document.createTextNode(']'));

}

}

setTimeout('sprint.drawPortlet('+index+')', sprint.portlets[index].refresh * 1000);

};

sprint.showPreview=function(title, url) {

var aj = sajax_init_object();

if (aj) {

var wnd = document.createElement('div');

wnd.id='sprint_previewWindow';

wnd.style.position='fixed';

wnd.style.padding='10px';

wnd.style.zIndex=++m_zIndex;

wnd.style.backgroundColor='white';

wnd.style.border='2px solid #aaaaaa';

wnd.style.width='60em';

wnd.style.height='30em';

wnd.style.minWidth='20em';

wnd.style.minHeight='10em';

//This is where we place the preview window - TODO: Check for modern skin

var obj = document.getElementById('column-one');

obj.appendChild(wnd);

wnd.style.left=parseInt(window.innerWidth-wnd.clientWidth)/2 + 'px';

wnd.style.top=parseInt(window.innerHeight-wnd.clientHeight)/2 + 'px';

var hdr = document.createElement('div');

hdr.style.position='relative';

hdr.style.width='100%';

hdr.style.height='2em';

hdr.style.borderBottom='1px solid #aaaaaa';

hdr.style.cursor='move';

wnd.appendChild(hdr);

var closeButton = document.createElement('a');

closeButton.href='#';

closeButton.style.position='absolute';

closeButton.style.top='10px';

closeButton.style.right='10px';

closeButton.onclick = function () {wnd.parentNode.removeChild(wnd); return false;};

closeButton.innerHTML = '';

wnd.appendChild(closeButton);

var content = document.createElement('div');

content.id='sprint_previewContent';

content.style.position='relative';

content.style.clear='both';

content.style.overflow='scroll';

content.style.height=parseInt(wnd.clientHeight - hdr.offsetHeight - parseInt(wnd.style.padding)*2)+'px';

content.style.lineHeight='1.5em';

wnd.appendChild(content);

wnd.onmousedown=function(event) {

if (wnd.style.zIndex < m_zIndex) {

wnd.style.zIndex=++m_zIndex;

}

}

hdr.onmousedown=function(event) {

wnd.initialX = parseInt( event.clientX - wnd.offsetLeft );

wnd.initialY = parseInt( event.clientY - wnd.offsetTop );

window.onmouseup=function(event) {

window.onmousemove=null;

window.onmouseup=null;

wnd.style.opacity='';

content.style.display='';

}

window.onmousemove=function(event) {

if (!content.style.display) {

wnd.style.opacity='.8';

content.style.display='none';

}

wnd.style.left=event.clientX-wnd.initialX+'px';

wnd.style.top=event.clientY-wnd.initialY+'px';

}

}

var resize = document.createElement('div');

resize.id='sprint_previewResize';

resize.style.position='absolute';

resize.style.bottom='0px';

resize.style.right='0px';

resize.style.height='20px';

resize.style.width='20px';

resize.style.cursor='se-resize';

wnd.appendChild(resize);

resize.onmousedown=function(event) {

wnd.initialWidth = parseInt( event.clientX - wnd.offsetWidth );

wnd.initialHeight = parseInt( event.clientY - wnd.offsetHeight );

window.onmouseup=function(event) {

window.onmousemove=null;

window.onmouseup=null;

wnd.style.opacity='';

content.style.height=parseInt(wnd.clientHeight - hdr.offsetHeight - parseInt(wnd.style.padding)*2)+'px';

content.style.display='';

}

window.onmousemove=function(event) {

if (!content.style.display) {

wnd.style.opacity='.8';

content.style.display='none';

}

wnd.style.width=event.clientX-wnd.initialWidth-parseInt(wnd.style.padding)*2+'px';

wnd.style.height=event.clientY-wnd.initialHeight-parseInt(wnd.style.padding)*2+'px';

}

}

hdr.innerHTML=''+title+'';

content.innerHTML='Loading...';

aj.onreadystatechange = function() {

if(aj.readyState == 4 && aj.status == 200) {

var htm;

htm = aj.responseText;

content.innerHTML = htm;

content.id = 'bodyContent'; //TODO: Find a better way to make the page format correctly

}

}

aj.open("GET", url, true);

aj.send(null);

}

};

sprint.patrol=function(url) {

var myAjax = sajax_init_object();

myAjax.open("GET", url, true);

myAjax.send(null);

};

sprint.makePortlet=function(title, titleLink, id, enabled, toggleFunction) {

var sb = document.getElementById('sprint');

var a;

var hdr = document.getElementById('hdr' + id);

if (hdr) {

while (hdr.firstChild) {

hdr.removeChild(hdr.firstChild);

}

} else {

hdr = document.createElement('h5');

hdr.id = 'hdr' + id;

sb.appendChild(hdr);

}

if (titleLink) {

var a = document.createElement('a');

a.setAttribute('nopopup', 'true');

a.id = 'lnk' + id;

a.setAttribute('href', titleLink);

a.appendChild(document.createTextNode(title));

hdr.appendChild(a);

} else {

hdr.appendChild(document.createTextNode(title));

}

hdr.appendChild(document.createTextNode(' ['));

a = document.createElement('a');

a.setAttribute('nopopup', 'true');

a.id = 'show' + id;

a.setAttribute('href', '#');

a.setAttribute('onclick', toggleFunction+';return false;');

if (enabled) {

a.appendChild(document.createTextNode('hide'));

} else {

a.appendChild(document.createTextNode('show'));

}

hdr.appendChild(a);

hdr.appendChild(document.createTextNode(']'));

hdr.appendChild(document.createElement('br'));

var p = document.getElementById(id);

if (!p) {

p = document.createElement('div');

p.setAttribute('class', 'pBody');

p.setAttribute('id', id);

sb.appendChild(p);//, document.getElementById('sprint_ovl'));

}

if (enabled) {

p.style.display='';

} else {

p.style.display='none';

}

};

sprint.createLine=function(pBody) {

var p = document.createElement('p');

p.style.lineHeight='1em';

p.style.fontSize='95%';

p.style.margin='0px';

p.style.padding='.1em';

pBody.appendChild(p);

return p;

};

sprint.toggleSprint=function() {

sprint.enabled = !sprint.enabled;

sprint.saveCookies();

sprint.drawSprint();

};

sprint.toggle=function(index) {

sprint.portlets[index].enabled = !sprint.portlets[index].enabled;

sprint.saveCookies();

sprint.drawPortlet(index);

};

sprint.readCookie=function(name) {

var nameEQ = name + "=";

var ca = document.cookie.split(';');

for(var i=0;i < ca.length;i++) {

var c = ca[i];

while (c.charAt(0)==' ') { c = c.substring(1,c.length); }

if (c.indexOf(nameEQ) === 0) { return c.substring(nameEQ.length,c.length); }

}

return '';

};

$(sprint.init);