GitHub Sortable Filelist

appends sorting function to github directories

当前为 2014-11-11 提交的版本,查看 最新版本

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