Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
sidebar_queries = [
{ name: 'wl', url: "/w/api.php?format=xml&action=query&list=watchlist&wllimit=", tag: 'item'},
{ name: 'np', 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'},
{ name: 'onp', 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'},
{ name: 'rc', url: "/w/api.php?format=xml&action=query&list=recentchanges&rclimit=", tag: 'rc'}/*,
{ name: 'un', url: "/w/api.php?action=query&list=logevents&letype=newusers&format=xml&lelimit=", tag: 'item'}*/];

sidebar = {
    enabled:               false,
    scrollwithpage:        false,
    paused:                false,
    portlets: [
{ type: 'query', name: 'Watchlist', query:'wl', enabled: true, items: 10, refresh: 5, titlelink:'/wiki/Special:Watchlist' },
{ type: 'query', name: 'New pages', query:'np', enabled: true, items: 10, refresh: 5, titlelink:'/wiki/Special:NewPages' },
{ type: 'query', name: 'Old unpatrolled', query:'onp', enabled: true, items: 10, refresh: 5, titlelink:'/w/index.php?title=Special:NewPages&dir=prev&hidepatrolled=1' },
{ type: 'query', name: 'Recent changes', query:'rc', enabled: true, items: 10, refresh: 5, titlelink:'/w/index.php?title=Special:RecentChanges&limit=50&hideliu=1' },
/*{ type: 'query', name: 'Usernames', query:'un', enabled: true, items: 10, refresh: 5, titlelink:'/w/index.php?title=Special%3ALog&type=newusers&user=&page='},*/
{ type: 'links', name: 'Bookmarks', enabled: true, links: [] }
    ],
    ajax: []
};

sidebar.loadCookies=function() {
    sidebar.enabled = (sidebar.readCookie('sidebar_enabled')=='true');
    //sidebar.scrollwithpage = (sidebar.readCookie('sidebar_scrollwithpage')=='true');

    var cookie = sidebar.readCookie('sidebar_portlets');
    if (cookie) {
        sidebar.portlets = [];
        var arrPortlets = cookie.split('||');
        for (var i=0; i<arrPortlets.length; i++) {
            sidebar.portlets[i]={};
            var s = arrPortlets[i].split('|');
            switch (s[0]) {
              case 'query':
                sidebar.portlets[i].type = 'query';
                sidebar.portlets[i].name = s[1];
                sidebar.portlets[i].query = s[2];
                sidebar.portlets[i].enabled = (s[3]=='true');
                sidebar.portlets[i].items = s[4];
                sidebar.portlets[i].refresh = s[5];
                sidebar.portlets[i].titlelink = s[6];
                break;
              case 'links':
                sidebar.portlets[i].type = 'links';
                sidebar.portlets[i].name = s[1];
                sidebar.portlets[i].enabled = (s[2]=='true');
                sidebar.portlets[i].links = sidebar.readCookie('sidebar_'+s[1]).split('||');
                break;
            }
        }
    }
}

sidebar.saveCookies=function() {
    var cend = "; expires=Tue, 31-Dec-2030 23:59:59 GMT; path=/";
    
    document.cookie = 'sidebar_enabled=' + sidebar.enabled.toString() + cend;
    //document.cookie = 'sidebar_scrollwithpage=' + sidebar.scrollwithpage.toString() + cend;
    
    var arr = [];
    for (var i=0; i<sidebar.portlets.length; i++) {
        var p = sidebar.portlets[i];
        switch (p.type) {
          case 'query':
            arr[i] = p.type +'|'+ p.name +'|'+ p.query +'|'+ p.enabled.toString() +'|'+ p.items +'|'+ p.refresh +'|'+ p.titlelink;
            break;
          case 'links':
            arr[i] = p.type +'|'+ p.name +'|'+ p.enabled.toString();
            var s = '';
            if (p.links) {
                s = p.links.join('||');
            }
            document.cookie = 'sidebar_'+p.name+'=' + s + cend;
            break;
        }
    }
    document.cookie = 'sidebar_portlets='+arr.join('||')+cend;
}

sidebar.pause = function () {
    sidebar.paused=true;
    p = document.getElementById('sidebar_ovl');
    if (p) {
        p.style.display='';
    }
};

sidebar.refresh = function () {
    if(sidebar.paused) {
        sidebar.paused=false;
        p = document.getElementById('sidebar_ovl');
        if (p) {
            p.style.display='none';
        }
        sidebar.loadCookies();
        sidebar.drawSidebar();
    }
};

sidebar.init = function () {
    sidebar.loadCookies();
    addPortletLink ('p-navigation', '#', 'Sidebar', 'toggleSidebar');
    document.getElementById('toggleSidebar').setAttribute('onclick', 'sidebar.toggleSidebar();return false;');
    sidebar.drawSidebar();

    window.onblur = sidebar.pause;
    window.onfocus = sidebar.refresh;
};

sidebar.drawSidebar=function() {
    sb = document.getElementById('sidebar');
    if (sidebar.enabled) {
        if (sb) {
            sb.style.display='';
        } else {
            sb = document.createElement('div');
            sb.id='sidebar';
            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;

            //container = document.getElementById('p-personal').parentNode; - this works in place of the next line
            container = document.getElementById('content');
            if (!container) {
                container = document.getElementById('mw_content');
            }
            container.appendChild(sb);

/* configuration disabled for now
            div = document.createElement('div');
            div.id='sidebar_configure';
            div.style.position='absolute';
            div.style.right='1em';
            div.style.bottom='1em';
            div.style.fontSize='x-small';
            a = document.createElement('a');
            a.setAttribute('nopopup', 'true');
            a.href = "#";
            a.setAttribute('onclick', 'sidebar.showConfigure();return false;');
            a.appendChild(document.createTextNode('configure sidebar'));
            div.appendChild(a)
            sb.appendChild(div);
*/

            div = document.createElement('div');
            div.id='sidebar_ovl';
            div.style.position='absolute';
            div.style.top='0px';
            div.style.right='0px';
            div.style.width='100%';
            div.style.height='100%';
            sb.style.borderLeft='1px solid #bbbbbb;';
            sb.style.backgroundColor=document.defaultView.getComputedStyle(document.body, null).backgroundColor;
            div.style.opacity='.7';
            div.zIndex=100;
            div.style.display='none';
            sb.appendChild(div);

/* we don't need a header
            div = document.createElement('div');
            div.id='sidebar_header';
            div.style.backgroundColor='#F2F2CE';
            div.style.border='1px solid #BFBFA3';
            div.style.margin='.1em';
            div.style.lineHeight='2em';
            div.style.textAlign='center';
            div.style.fontWeight='bold';
            div.appendChild(document.createTextNode('Sidebar'));
            span = document.createElement('span');
            span.style.fontWeight='normal';
            span.appendChild(document.createTextNode(' ['));
            a = document.createElement('a');
            a.setAttribute('nopopup', 'true');
            a.href = "#";
            a.setAttribute('onclick', 'sidebar.toggleSidebar();return false;');
            a.appendChild(document.createTextNode('hide'));
            span.appendChild(a);
            span.appendChild(document.createTextNode(']'));
            div.appendChild(span);
            sb.appendChild(div);
*/
        }

        if (sidebar.scrollwithpage) {
            sb.style.position='absolute';
        } else {
            sb.style.position='fixed';
        }
        
        var spacer = (sb.offsetWidth)+'px';
        
/*
        mwheader = document.getElementById('mw_header'); //modern skin only
        if (mwheader) {
            mwheader.style.marginRight=spacer;
            mwheader.style.position='static';
        }
*/
        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;
        }

        //document.body.style.marginRight=spacer; - this works too
        sb.parentNode.style.marginRight=spacer;

        for (var i=0; i<sidebar.portlets.length; i++) {
            sidebar.drawPortlet(i);
        }
        
    } else {
        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='';
        }
        //document.body.style.marginRight=''; - this works too
        if (sb) {
            sb.parentNode.style.marginRight='';
            sb.style.display='none';       
        }
    }
}

sidebar.drawPortlet=function(index) {
    if (!sidebar.enabled || sidebar.paused) return false;
    var ptl = sidebar.portlets[index];
    sidebar.makePortlet(ptl.name, ptl.titlelink, 'p-sb'+index, ptl.enabled, 'sidebar.toggle('+index+')');
    
    if (ptl.enabled) {
        if (ptl.type=='query') {
            if (!sidebar.ajax) {
                sidebar.ajax = [];
            }
            sidebar.ajax[index] = sajax_init_object();
            if (sidebar.ajax[index]) {
                var queryIndex = null;
                for (var j=0; j<sidebar_queries.length; j++) {
                    if (sidebar_queries[j].name==ptl.query) {
                        queryIndex = j;
                    }
                }

                sidebar.ajax[index].onreadystatechange = function() {
                    if(sidebar.ajax[index].readyState == 4) {sidebar.portletCallback(index, queryIndex);}
                };
                
                url = sidebar_queries[queryIndex].url + ptl.items;
                    
                sidebar.ajax[index].open("GET", url, true);
                sidebar.ajax[index].send(null);
            } else {
                pBody = document.getElementById('p-sb'+index);
                while (pBody.firstChild) {
                    pBody.removeChild(pBody.firstChild);
                }                    
            }
        } else if (ptl.type=='links') {
            pBody = document.getElementById('p-sb'+index);    
            while (pBody.firstChild) {
                pBody.removeChild(pBody.firstChild);
            }
            for (var i=0; i<ptl.links.length; i++) {
                var url = ptl.links[i].split('|')[0];
                var title = ptl.links[i].split('|')[1];
                if (url && title) {
                    var p = createLine(pBody);
                    var a = document.createElement('a');
                    //a.setAttribute('nopopup', 'true'); //FIXME
                    a.href = url;
                    a.title = title;
                    a.appendChild(document.createTextNode(title));
                    p.appendChild(a);                
                    p.appendChild(document.createTextNode(' ('));
                    a = document.createElement('a');
                    a.setAttribute('nopopup', 'true');
                    a.setAttribute('href', '#');
                    a.setAttribute('onclick', 'sidebar.removeBookmark('+index+','+i+');return false;');
                    a.appendChild(document.createTextNode('x'));
                    p.appendChild(a);
                    p.appendChild(document.createTextNode(')'));
                }
            }

            var p = createLine(pBody);
            p.style.lineHeight="100%";
            p.style.fontSize = 'x-small';
            p.style.margin = '0px';
            p.style.textAlign = 'right';
            var a = document.createElement('a');
            a.setAttribute('nopopup', 'true');
            a.href = '#';
            a.setAttribute('onclick', 'sidebar.addBookmark('+index+');return false;');
            a.appendChild(document.createTextNode('add'));
            p.appendChild(a);
        }
    }
}

sidebar.portletCallback=function(index, queryIndex) {
    pBody = document.getElementById('p-sb'+index);
    while (pBody.firstChild) {
        pBody.removeChild(pBody.firstChild);
    }
    
    var url = sidebar_queries[queryIndex].url;
    var tag = sidebar_queries[queryIndex].tag;
    var patrol = (url.indexOf('patrolled')>=0);

    var items;    
    try {
        items = sidebar.ajax[index].responseXML.documentElement.getElementsByTagName(tag);
    } catch (e) {
        //var p = createLine(pBody);
        //p.appendChild(document.createTextNode('update failed2'));
        return;
    }
    for (var i=0; i<items.length; i++) {
        var title = items[i].getAttribute('title');//.replace(/&/, "%26", "g");
        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 (rcid) {
//            if (patrol) not_patrolled = (items[i].getAttribute('patrolled')==null);
//            item_url = mw.config.get('wgScript') + '?title=' + escape(title.replace(' ', '_', "g")) + '&rcid=' + rcid;//+ '&redirect=no'; (this screws up Friendly)
//        } else {
//            //item_url = mw.config.get('wgArticlePath').replace("$1", escape(title.replace(' ', '_', "g")));
//            item_url = mw.config.get('wgScript') + '?title=' + escape(title.replace(' ', '_', "g")) + '&oldid=' + revid;
//        }

        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'); //FIXME
        a.href=item_url;
        a.title=title;
        a.appendChild(document.createTextNode(title));
        
        var p = createLine(pBody);
        p.appendChild(a);
        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', 'sidebar.patrol("'+item_url+'&action=markpatrolled");return false;');
            ap.appendChild(document.createTextNode('p'));
            p.appendChild(ap);
            p.appendChild(document.createTextNode(']'));
        }
    }
    
    setTimeout('sidebar.drawPortlet('+index+')', sidebar.portlets[index].refresh * 1000);
}

sidebar.patrol=function(url) {
    myAjax = sajax_init_object();
    myAjax.open("GET", url, true);
    myAjax.send(null);
}

sidebar.addBookmark=function(portletIndex) {
    var url = window.location.pathname+window.location.search+window.location.hash;
    for (var i=0; i<sidebar.portlets[portletIndex].links.length; i++)
    {
        if (sidebar.portlets[portletIndex].links[i].split('|')[0] == url)
        {
            return;
        }
    }
    sidebar.portlets[portletIndex].links.push(url + '|' + mw.config.get('wgTitle'));
    sidebar.saveCookies();
    sidebar.drawPortlet(portletIndex);
}

sidebar.removeBookmark=function(portletIndex, index) {
    sidebar.portlets[portletIndex].links.splice(index, 1);
    sidebar.saveCookies();
    sidebar.drawPortlet(portletIndex);
}

sidebar.makePortlet=function(title, titleLink, id, enabled, toggleFunction) {
    var sb = document.getElementById('sidebar');
    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);
    }
    
    if (enabled) {
        p.style.display='';
    } else {
        p.style.display='none';
    }
}

function createLine(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;
}

sidebar.toggleSidebar=function() {
    sidebar.enabled = !sidebar.enabled;
    sidebar.saveCookies();
    sidebar.drawSidebar();
}
sidebar.toggle=function(index) {
    sidebar.portlets[index].enabled = !sidebar.portlets[index].enabled;
    sidebar.saveCookies();
    sidebar.drawPortlet(index);
}

sidebar.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 '';
}

sidebar.showConfigure=function() {
    var sb = document.getElementById('sidebar');
    var ovl = document.createElement('div');
    ovl.id='sbc_ovl';
    ovl.style.position='fixed';
    ovl.style.left=0;
    ovl.style.top=0;
    ovl.style.width='100%';
    ovl.style.height='100%';
    ovl.style.zIndex=99;
    ovl.style.backgroundColor='gray';
    ovl.style.opacity='.2';
    ovl.setAttribute('onclick', 'sidebar.hideConfigure();return false;');
    sb.parentNode.appendChild(ovl);
    
    var wnd = document.createElement('div');
    wnd.id='sbc_wnd';
    wnd.style.position='fixed';
    wnd.style.left='50%';
    wnd.style.top=ovl.clientHeight/2+'px';
    wnd.style.width='60em';
    wnd.style.height='40em';
    wnd.style.marginLeft='-30em';
    wnd.style.marginTop='-20em';
    wnd.style.padding='.5em';
    wnd.style.zIndex=100;
    wnd.style.backgroundColor='#FFFFF5';
    wnd.style.border='1px solid #BFBFA3';
    wnd.style.opacity='1';
    sb.parentNode.appendChild(wnd);

    div = document.createElement('div');
    div.id='sbc_hdr';
    div.style.backgroundColor='#F2F2CE';
    div.style.border='1px solid #BFBFA3';
    div.style.margin='.1em';
    div.style.lineHeight='2em';
    div.style.textAlign='center';
    div.style.fontWeight='bold';
    div.appendChild(document.createTextNode('Sidebar Configuration'));
    span = document.createElement('span');
    span.style.fontWeight='normal';
    span.appendChild(document.createTextNode(' ['));
    a = document.createElement('a');
    a.setAttribute('nopopup', 'true');
    a.href = "#";
    a.setAttribute('onclick', 'sidebar.hideConfigure();return false;');
    a.appendChild(document.createTextNode('hide'));
    span.appendChild(a);
    span.appendChild(document.createTextNode(']'));
    div.appendChild(span);
    wnd.appendChild(div);
}

sidebar.hideConfigure=function() {
    var div = document.getElementById('sbc_ovl');
    div.parentNode.removeChild(div);
    div = document.getElementById('sbc_wnd');
    div.parentNode.removeChild(div);
}

addOnloadHook(sidebar.init);