GitHub Sortable Filelist

appends sorting function to github directories

目前为 2014-11-12 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name GitHub Sortable Filelist
  3. // @namespace trespassersW
  4. // @description appends sorting function to github directories
  5. // @include https://github.com/*
  6. // @version 14.11.11.6
  7. // .6 fix
  8. // .4 now works on all github pages
  9. // @created 2014-11-10
  10. // @updated 2014-11-11
  11. // @author trespassersW
  12. // @licence MIT
  13. // @run-at document-end
  14. // @grant GM_none
  15. // ==/UserScript==
  16.  
  17. if(document.body || document.querySelector('#js-repo-pjax-container')){ // .file-wrap
  18.  
  19. var llii=0; function _l(m){/* * /
  20. console.log(++llii +': '+m)
  21. /* */}
  22.  
  23. (function(){ "use strict";
  24.  
  25. function stickStyle(css){
  26. var s=document.createElement("style"); s.type="text/css";
  27. s.appendChild(document.createTextNode(css));
  28. return (document.head||document.documentElement).appendChild(s);
  29. }
  30. function insBefore(n,e){
  31. return e.parentNode.insertBefore(n,e);
  32. }
  33. function insAfter(n,e){
  34. if(e.nextElementSibling)
  35. return e.parentNode.insertBefore(n,e.nextElementSibling);
  36. return e.parentNode.appendChild(n);
  37. }
  38. function outerNode(target, node) {
  39. if (target.nodeName==node) return target;
  40. if (target.parentNode)
  41. while (target = target.parentNode) try{
  42. if (target.nodeName==node)
  43. return target;
  44. }catch(e){};
  45. return null;
  46. }
  47.  
  48. function css(){
  49. stickStyle('\
  50. .fsort-butt, .tables.file {position: relative; }\
  51. .fsort-butt:before{\
  52. position: absolute; left:1.5em; top: -1em; \
  53. cursor: pointer;\
  54. content: "";\
  55. z-index:99999;\
  56. width: 0; height: 0;\
  57. opacity:.2;\
  58. }\
  59. .fsort-asc:before,\
  60. .fsort-desc.fsort-sel:hover:before\
  61. {\
  62. border-left: 6px solid transparent;\
  63. border-right: 6px solid transparent;\
  64. border-bottom: 14px solid #444;\
  65. border-top: 0;\
  66. }\
  67. .fsort-desc:before,\
  68. .fsort-asc.fsort-sel:hover:before{\
  69. border-left: 6px solid transparent;\
  70. border-right: 6px solid transparent;\
  71. border-bottom: 0;\
  72. border-top: 14px solid #444;\
  73. }\
  74. .fsort-butt.fsort-desc.fsort-sel:hover:before,\
  75. .fsort-butt.fsort-asc.fsort-sel:before{\
  76. border-bottom: 14px solid #4183C4;\
  77. border-top: 0;\
  78. }\
  79. .fsort-butt.fsort-desc.fsort-sel:before,\
  80. .fsort-butt.fsort-asc.fsort-sel:hover:before{\
  81. border-bottom: 0;\
  82. border-top: 14px solid #4183C4;\
  83. }\
  84. \
  85. .fsort-butt.fsort-sel:before{ opacity: .6 }\
  86. .fsort-butt:hover:before{ opacity: 1 !important;}\
  87. /* patches */\
  88. table.files td.age {text-align: left !important;}\
  89. table.files td.message {overflow-y: visible !important;}\
  90. ');//#80A6CD
  91. }
  92. var ii=0;
  93. var d0=[0,0,1];
  94. var C=[{c:1, d: 0, s: 0},{c:2, d: 0, s: 0},{c:3, d: 1, s: 0}];
  95. var ASC;
  96. var oa=[],ca=[];
  97. var D=document, TB;
  98. var catcher;
  99. function setC(n){
  100. for(var i=0,il=C.length; i<il; i++ ){
  101. if(i!=n) C[i].s= 0, C[i].d=d0[i];
  102. else C[i].s=1;
  103. oa[i].className='fsort-butt fsort-'+(C[i].d?'desc':'asc')+(C[i].s?' fsort-sel':'') ;
  104. oa[i].title=C[i].d? '\u21ca' : '\u21c8';
  105. }
  106. }
  107.  
  108. function isDir(x){
  109. return (TB.rows[x].cells[0].querySelector("span.octicon-file-directory")) != null;
  110. }
  111.  
  112. var sDir,sCells;
  113. var fa=[
  114. function(a){
  115. sCells.push(TB.rows[a].cells[1].querySelector('span.css-truncate-target a').textContent);
  116. },
  117. function(a){
  118. sCells.push(TB.rows[a].cells[2].querySelector('span.css-truncate').textContent);
  119. },
  120. function(a){
  121. sCells.push(TB.rows[a].cells[3].querySelector('span.css-truncate>time').getAttribute('datetime'));
  122. }
  123. ]
  124. function sort_p(n){// prepare data for sorting
  125. sDir=[],sCells=[];
  126. for(var tl=TB.rows.length, a=0; a<tl; a++){
  127. sDir.push(isDir(a));
  128. fa[n](a);
  129. }
  130. }
  131.  
  132. function sort_fn(a,b){
  133. var x=sDir[a], y=sDir[b];
  134. if(x!=y) return ((x<y)<<1)-1;
  135. x= sCells[a], y= sCells[b];
  136. return x==y? 0: (((x>y)^ASC)<<1)-1;
  137. }
  138. var CNn={content: 0, message: 1, age: 2}
  139.  
  140. function oClr(){
  141. var o= catcher.querySelectorAll('.fsort-butt')
  142. for(var ol=o.length,i=0;i<ol;i++)
  143. o[i].parentNode.removeChild(o[i]);
  144. }
  145. //
  146. function doSort(t){
  147. TB=outerNode(t,'TBODY');
  148. var tb=[],ix=[], i, tl;
  149. if(!TB){ _l( "*GHSFL* TBODY not found"); return; }
  150. var n=CNn[t.parentNode.className];
  151. if(typeof n=="undefined"){ _l( "*GHSFL* undefined col"); return; }
  152. _l('n:'+n);
  153. tl=TB.rows.length;
  154. ASC=C[n].d^=C[n].s;
  155. for( i=0; i<tl; i++)
  156. ix.push(i);
  157. oClr();
  158. sort_p(n);
  159. ix.sort(sort_fn);
  160. for( i=0; i<tl; i++)
  161. tb.push(TB.rows[ix[i]].innerHTML);
  162. for( i=0; i<tl; i++)
  163. TB.rows[i].innerHTML=tb[i];
  164. setC(n);
  165. gitDir1(0);
  166. }
  167.  
  168. function onClik(e){doSort(e.target)}
  169.  
  170. function gitDir1(x){
  171. if(x && document.querySelector('.fsort-butt')) {
  172. _l('gitDir'+x+' - already'); return;
  173. }
  174. _l('gitDir'+x)
  175. var c,o;
  176. ca=[];
  177. c= D.querySelector('.file-wrap table.files td.content >span');
  178. if(!c){ _l( '*GHSFL* no content') ; return; }
  179. ca.push(c);
  180. c=D.querySelector('.file-wrap table.files td.message >span');
  181. if(!c){ _l( '*GHSFL* no messages'); return; }
  182. ca.push(c);
  183. c=D.querySelector('.file-wrap table.files td.age >span');
  184. if(!c){_l( '*GHSFL* no ages'); return; }
  185. ca.push(c);
  186. if(x){ oClr(); oa=[];
  187. o=D.createElement('span');
  188. o.textContent='';
  189. oa.push(o);
  190. o=o.cloneNode(true);
  191. oa.push(o);
  192. o=o.cloneNode(true);
  193. oa.push(o);
  194. setC(-1);
  195. }
  196. insBefore(oa[0],ca[0]);
  197. insBefore(oa[1],ca[1]);
  198. insBefore(oa[2],ca[2]);
  199. }
  200.  
  201. function gitDir(){
  202. gitDir1(1);
  203. }
  204.  
  205. catcher= D.querySelector('#js-repo-pjax-container');
  206. if(!catcher){ _l( "*GHSFL* err0r"); return; }
  207.  
  208. catcher.addEventListener('mousedown',function(e){
  209. if(e.target.nodeName && e.target.nodeName=='SPAN' &&
  210. e.target.className.indexOf('fsort-butt')>-1)
  211. { onClik(e); }
  212. }
  213. ,false);
  214. _l('startup()');
  215. css();
  216. gitDir();
  217. window.GH_SFL=C;
  218. var target = catcher; //document.body; //D.querSelector('.file-wrap');
  219. var MO = window.MutationObserver;
  220. if(!MO) MO= window.WebKitMutationObserver;
  221. if(!MO) return;
  222. var observer = new MO(function(mutations) {
  223. mutations.forEach(function(m) {
  224. if( m.type= "attributes" &&
  225. m.target.nodeName == 'DIV' &&
  226. m.target.className == "file-wrap" )
  227. gitDir();
  228. return;
  229. });
  230. });
  231.  
  232. //if(m.target.nodeName!='TIME')_l('mo'+' '+m.type +'.'+m.target.nodeName+m.target.className));
  233.  
  234. observer.observe(D.body, { attributes: true, subtree: true } );
  235. /* attributes: true , childList: true, subtree: true,
  236. characterData: true, attributeOldValue:true, characterDataOldValue:true
  237. */
  238.  
  239. })()};
  240.  
  241. /*
  242. to do: persistent settings; sorting by file extensions; toggling date/time display mode
  243. ... do we really need it?
  244. */