// ==UserScript==
// @name GitHub Sortable Filelist
// @namespace trespassersW
// @description appends sorting function to github directories
// @include https://github.com/*
// @version 14.11.11.1
// .1 optimization; span.title
// @created 2014-11-10
// @updated 2014-11-11
// @author trespassersW
// @licence MIT
// @run-at document-end
// @grant GM_none
// ==/UserScript==
if(document.querySelector('.file-wrap')){
(function(){ "use strict";
var llii=0; function _l(m){ if(1) console.log(++llii +': '+m) }
function stickStyle(css){
var s=document.createElement("style"); s.type="text/css";
s.appendChild(document.createTextNode(css));
return (document.head||document.documentElement).appendChild(s);
}
function insBefore(n,e){
return e.parentNode.insertBefore(n,e);
}
function insAfter(n,e){
if(e.nextElementSibling)
return e.parentNode.insertBefore(n,e.nextElementSibling);
return e.parentNode.appendChild(n);
}
function outerNode(target, node) {
if (target.nodeName==node) return target;
if (target.parentNode)
while (target = target.parentNode) try{
if (target.nodeName==node)
return target;
}catch(e){};
return null;
}
function css(){
stickStyle('\
.fsort-butt, .tables.file {position: relative; }\
.fsort-butt:before{\
position: absolute; left:1.5em; top: -1em; \
cursor: pointer;\
content: "";\
z-index:99999;\
width: 0; height: 0;\
opacity:.2;\
}\
.fsort-asc:before,\
.fsort-desc.fsort-sel:hover:before\
{\
border-left: 6px solid transparent;\
border-right: 6px solid transparent;\
border-bottom: 14px solid #444;\
border-top: 0;\
}\
.fsort-desc:before,\
.fsort-asc.fsort-sel:hover:before{\
border-left: 6px solid transparent;\
border-right: 6px solid transparent;\
border-bottom: 0;\
border-top: 14px solid #444;\
}\
.fsort-butt.fsort-desc.fsort-sel:hover:before,\
.fsort-butt.fsort-asc.fsort-sel:before{\
border-bottom: 14px solid #4183C4;\
border-top: 0;\
}\
.fsort-butt.fsort-desc.fsort-sel:before,\
.fsort-butt.fsort-asc.fsort-sel:hover:before{\
border-bottom: 0;\
border-top: 14px solid #4183C4;\
}\
\
.fsort-butt.fsort-sel:before{ opacity: .6 }\
.fsort-butt:hover:before{ opacity: 1 !important;}\
/* patches */\
table.files td.age {text-align: left !important;}\
table.files td.message {overflow-y: visible !important;}\
');//#80A6CD
}
var ii=0;
var d0=[0,0,1];
var C=[{c:1, d: 0, s: 0},{c:2, d: 0, s: 0},{c:3, d: 1, s: 0}];
var ASC;
var oa=[],ca=[];
var D=document, TB;
var catcher;
function setC(n){
for(var i=0,il=C.length; i<il; i++ ){
if(i!=n) C[i].s= 0, C[i].d=d0[i];
else C[i].s=1;
oa[i].className='fsort-butt fsort-'+(C[i].d?'desc':'asc')+(C[i].s?' fsort-sel':'') ;
oa[i].title=C[i].d? '\u21ca' : '\u21c8';
}
}
function isDir(x){
return (TB.rows[x].cells[0].querySelector("span.octicon-file-directory")) != null;
}
var sDir,sCells;
var sort_p= [ // prepare data for sorting
function(){
sDir=[],sCells=[];
for(var tl=TB.rows.length, a=0; a<tl; a++){
sDir.push(isDir(a));
sCells.push(TB.rows[a].cells[1].querySelector('span.css-truncate-target a').textContent);
}
}
,
function(){
sDir=[],sCells=[];
for(var tl=TB.rows.length, a=0; a<tl; a++){
sDir.push(isDir(a));
sCells.push(TB.rows[a].cells[2].querySelector('span.css-truncate').textContent);
}
}
,
function(){
sDir=[],sCells=[];
for(var tl=TB.rows.length, a=0; a<tl; a++){
sDir.push(isDir(a));
sCells.push(TB.rows[a].cells[3].querySelector('span.css-truncate>time').getAttribute('datetime'));
}
}
]
function sort_fn(a,b){
var x=sDir[a], y=sDir[b];
if(x!=y) return ((x<y)<<1)-1;
x= sCells[a], y= sCells[b];
return x==y? 0: (((x>y)^ASC)<<1)-1;
}
var CNn={content: 0, message: 1, age: 2}
function oClr(){
var o= catcher.querySelectorAll('.fsort-butt')
for(var ol=o.length,i=0;i<ol;i++)
o[i].parentNode.removeChild(o[i]);
}
//
function doSort(t){
TB=outerNode(t,'TBODY');
var tb=[],ix=[], i, tl;
if(!TB) throw "*GHSFL* TBODY not found";
var n=CNn[t.parentNode.className];
if(typeof n=="undefined") throw "*GHSFL* undefined col";
_l('n:'+n);
tl=TB.rows.length;
ASC=C[n];
ASC=C[n].d^=C[n].s;
for( i=0; i<tl; i++)
ix.push(i);
oClr();
sort_p[n]();
ix.sort(sort_fn);
for( i=0; i<tl; i++)
tb.push(TB.rows[ix[i]].innerHTML);
for( i=0; i<tl; i++)
TB.rows[i].innerHTML=tb[i];
setC(n);
gitDir1(0);
}
function onClik(e){doSort(e.target)}
function gitDir1(x){
if(x && document.querySelector('.fsort-butt')) {
_l('gitDir'+x+' - already'); return;
}
_l('gitDir'+x)
var c,o;
ca=[];
c= D.querySelector('.file-wrap table.files td.content >span');
if(!c) throw '*GHSFL* no content';
ca.push(c);
c=D.querySelector('.file-wrap table.files td.message >span');
if(!c) throw '*GHSFL* no messages';
ca.push(c);
c=D.querySelector('.file-wrap table.files td.age >span');
if(!c) throw '*GHSFL* no ages';
ca.push(c);
if(x){ oClr(); oa=[];
o=D.createElement('span');
o.textContent='';
oa.push(o);
o=o.cloneNode(true);
oa.push(o);
o=o.cloneNode(true);
oa.push(o);
setC(-1);
}
insBefore(oa[0],ca[0]);
insBefore(oa[1],ca[1]);
insBefore(oa[2],ca[2]);
}
function gitDir(){
gitDir1(1);
}
catcher= D.querySelector('#js-repo-pjax-container');
if(!catcher) throw "*GHSFL* err0r";
catcher.addEventListener('mousedown',function(e){
if(e.target.nodeName && e.target.nodeName=='SPAN' &&
e.target.className.indexOf('fsort-butt')>-1)
{ onClik(e); }
}
,false);
_l('startup()');
css();
gitDir();
window.GH_SFL=C;
var target = catcher; //document.body; //D.querSelector('.file-wrap');
var MO = window.MutationObserver;
if(!MO) MO= window.WebKitMutationObserver;
if(!MO) return;
var observer = new MO(function(mutations) {
mutations.forEach(function(m) {
if( m.type= "attributes" &&
m.target.nodeName == 'DIV' &&
m.target.className == "file-wrap" )
gitDir(0);
});
});
observer.observe(D.body, { attributes: true, subtree: true } );
/* attributes: true , childList: true, subtree: true,
characterData: true, attributeOldValue:true, characterDataOldValue:true
*/
})()};
/*
to do: persistent settings; sorting by file extensions; toggling date/time display mode
... do we really need it?
*/