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.
//helpers
function newNode(type,text,attr1,cont1,attr2,cont2,attr3,cont3,attr4,cont4) {
	var a = document.createElement(type)
	if (text>'') a.textContent = text
	if (attr1>'') a.setAttribute(attr1,cont1)
	if (attr2>'') a.setAttribute(attr2,cont2)
	if (attr3>'') a.setAttribute(attr3,cont3)
	if (attr4>'') a.setAttribute(attr4,cont4)
	return a
}
function newControl(label,onclik) {
	var a = newNode('a',label)
	a.onclick=onclik
	return a
}

//master switch
function updateCSS() {
	if ( isRow &&  isSorted) document.getElementById('CatVisorStyle').textContent = CatVisor_style_base + CatVisor_style_row
                                                                                  + CatVisor_style_sorted + CatVisor_style_first
	if ( isRow && !isSorted) document.getElementById('CatVisorStyle').textContent = CatVisor_style_base + CatVisor_style_row
	if (!isRow &&  isSorted) document.getElementById('CatVisorStyle').textContent = CatVisor_style_base + CatVisor_style_column + CatVisor_style_sorted
	if (!isRow && !isSorted) document.getElementById('CatVisorStyle').textContent = CatVisor_style_base + CatVisor_style_column
}
function flexsort()   { isSorted = true;  updateCSS() }
function flexunsort() { isSorted = false; updateCSS() }
function flexrow()    { isRow    = true;  updateCSS() }
function flexcolumn() { isRow    = false; updateCSS() }

//find objects of interest
var catbox            = document.getElementById('catlinks')
var catbox_normal_ul  = document.getElementById('mw-normal-catlinks').getElementsByTagName('ul')[0]
catbox_normal_ul.setAttribute('id','catlist')
var catbox_normal_lis = catbox_normal_ul.getElementsByTagName('li')
 
//add stylesheet, create style fragments
catbox.appendChild(newNode("style",CatVisor_style_base,'id','CatVisorStyle','type','text/css'))
var CatVisor_style_base     =   '#CatVisorControls a {cursor:pointer; margin-right:0.25em}\n'
                              + '#CatVisorControls a:first-child:after {content:":"}\n'
                              + '#catlist {display:-ms-flexbox; display:flex; -ms-flex-wrap:wrap; flex-wrap:wrap}\n'
                                //nail "add new category" to the last position when HotCat is enabled
                              + '#catlist li.noprint {-ms-flex-order:666666; order:666666}\n'
var CatVisor_style_row      =   '#catlist {-ms-flex-direction:row; flex-direction:row}\n'
var CatVisor_style_column   =   '#catlist {-ms-flex-direction:column; flex-direction:column}\n'
                              + '#catlist li {border-left:none; padding-left:0.5em}\n'
var CatVisor_style_first    =   '#catlist li:first-child {border-left:1px solid #AAA; padding-left:0.5em}\n'
                              + '#firstinsorted {border-left:none; padding-left:0.25em}\n'
//compute alphabetic ordering
var alphaindex = []
for (var i=0;i<catbox_normal_lis.length;i++) alphaindex[i]=i
alphaindex.sort(function(a,b){return(catbox_normal_lis[a].textContent>catbox_normal_lis[b].textContent)?1:-1})
var CatVisor_style_sorted   = ''
for (var i=0;i<catbox_normal_lis.length;i++)
	CatVisor_style_sorted += '#catlist li:nth-child('+(alphaindex[i]+1)+') {-ms-flex-order:'+i+'; order:'+i+'}\n'
//first element in row display is styled differently
catbox_normal_lis[alphaindex[0]].setAttribute("id","firstinsorted")

//add controls
controls = newNode('div','','id','CatVisorControls')
controls.appendChild(newNode('a','CatVisor','href','http://en.wikipedia.org/wiki/User:Paradoctor/CatVisor'))
controls.appendChild(newControl('column'  ,flexcolumn))
controls.appendChild(newControl('row'     ,flexrow   ))
controls.appendChild(newControl('sorted'  ,flexsort  ))
controls.appendChild(newControl('unsorted',flexunsort))
catbox.insertBefore(controls,catbox.firstChild)

//set default and beat it
var isRow=true, isSorted=false;
updateCSS()