Tieba Utilities

百度贴吧依赖脚本(寂寞的原子的公共库)

目前為 2015-01-31 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Tieba Utilities
  3. // @namespace http://gera2ld.blog.163.com/
  4. // @author Gerald <gera2ld@163.com>
  5. // @icon http://ww2.sinaimg.cn/small/a56031a1gw1emwlbe1c8gj2097097wfa.jpg
  6. // @version 0.8.5
  7. // @description 百度贴吧依赖脚本(寂寞的原子的公共库)
  8. // @homepageURL http://geraldl.net/userjs/TiebaUtils
  9. // @match *://*.baidu.com/*
  10. // @include *.baidu.com/*
  11. // @run-at document-start
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. if(typeof unsafeWindow=='undefined') unsafeWindow=window;
  16. var shortcuts={},$=function(){
  17. $=unsafeWindow.$;
  18. return $.apply(this,arguments);
  19. },links={
  20. hotkey:'http://geraldl.net/userjs/TiebaUtils#hotkey',
  21. advanced:'http://geraldl.net/userjs/TiebaAdvanced#advanced',
  22. },utils={
  23. index:function(objs,obj,key){
  24. for(var i=0;i<objs.length;i++)
  25. if(objs[i][key]===obj) return i;
  26. return -1;
  27. },
  28. wait: (function(){
  29. var objs=[];
  30. function init(obj,name,callbacks){
  31. var value=undefined;
  32. Object.defineProperty(obj,name,{
  33. get:function(){return value;},
  34. set:function(val){
  35. value=val;
  36. if(callbacks) {
  37. console.log('waited: ',obj,name);
  38. callbacks.forEach(function(f){f(val);});
  39. callbacks=null;
  40. }
  41. },
  42. configurable:true,
  43. });
  44. }
  45. return function(obj,name,callback) {
  46. if(obj[name]) callback(obj[name]);
  47. else {
  48. var i=utils.index(objs,obj,'obj'),o=objs[i],c;
  49. if(!o) objs.push(o={obj:obj,callbacks:{}});
  50. c=o.callbacks[name];
  51. if(!c) c=o.callbacks[name]=[];
  52. c.push(callback);
  53. init(obj,name,c);
  54. }
  55. };
  56. })(),
  57. observe: (function(){
  58. var objs=[];
  59. function init(obj,o){
  60. // Opera Presto is not supported any more
  61. function observer(changes){
  62. changes.forEach(function(c){
  63. var d=o.data[c.name];
  64. if(d) {
  65. console.log('Observed: ',obj,c.name);
  66. d.forEach(function(f){f(obj[c.name]);});
  67. delete o.data[c.name];
  68. if(!--o.length) {
  69. o=objs.indexOf(o);
  70. if(o>=0) objs.splice(o,1);
  71. Object.unobserve(obj,observer,['add']);
  72. }
  73. }
  74. });
  75. }
  76. Object.observe(obj,observer,['add']);
  77. }
  78. return function(obj,name,callback) {
  79. if(name in obj) callback(obj[name]);
  80. else {
  81. var i=utils.index(objs,obj,'obj'),o=objs[i],d;
  82. if(!o) {
  83. objs.push(o={obj:obj,data:{},length:0});
  84. init(obj,o);
  85. }
  86. d=o.data[name];
  87. if(!d) {
  88. d=o.data[name]=[];
  89. o.length++;
  90. }
  91. d.push(callback);
  92. }
  93. };
  94. })(),
  95. find: function(selector,ancestor,callback){
  96. var o=$(selector,ancestor),mo;
  97. if(o.length) callback(o);
  98. else if(window.MutationObserver) {
  99. mo=new MutationObserver(function(changes){
  100. $.each(changes,function(i,e){
  101. $.each(e.addedNodes,function(i,o){
  102. o=$(o).find(selector);
  103. if(o.length) {
  104. mo.disconnect();
  105. callback(o);
  106. }
  107. });
  108. });
  109. });
  110. mo.observe(ancestor,{
  111. childList:true,
  112. subtree:true,
  113. });
  114. } else $(window).load(function(){
  115. callback($(selector,ancestor));
  116. });
  117. },
  118. hook: function(o,n,a) {
  119. var f;
  120. if(o&&(f=o[n])) {
  121. if(!f.hooked) {
  122. o[n]=function() {
  123. var t=this,a=arguments,f=a.callee,r=undefined,_r,i,stop=false;
  124. f.hookStop=function(){stop=true;};
  125. for(i=0;i<f.hook_before.length;i++){
  126. r=f.hook_before[i].apply(t,[f,a]);
  127. if(stop) return r;
  128. }
  129. r=f.hook_func.apply(t,a);
  130. for(i=0;i<f.hook_after.length;i++){
  131. _r=f.hook_after[i].apply(t,[f,r,a]);
  132. if(_r!==undefined) r=_r;
  133. if(stop) return r;
  134. }
  135. return r;
  136. };
  137. o[n].hook_func=f;
  138. f=o[n];
  139. f.hooked=true;
  140. f.hook_after=[];
  141. f.hook_before=[];
  142. }
  143. o=f.hook_after;
  144. if(n=a.after) {
  145. if(n.concat) f.hook_after=o.concat(n);
  146. else o.push(n);
  147. }
  148. o=f.hook_before;
  149. if(n=a.before) {
  150. if(n.concat) f.hook_before=o.concat(n);
  151. else o.push(n);
  152. }
  153. }
  154. },
  155. addStyle: function(css,id) {
  156. var s=document.getElementById(id)||document.createElement('style');
  157. if(id) s.id=id;if(css) s.innerHTML=css;
  158. document.head.appendChild(s);
  159. return $?$(s):s;
  160. },
  161. getObj: function(k,d) {
  162. var r=localStorage.getItem('ge_'+k),u=undefined,v=u;
  163. if(r) try{v=JSON.parse(r);}catch(e){}
  164. if(v==u&&d!=u) v=utils.setObj(k,d);
  165. return v;
  166. },
  167. setObj: function(k,v) {localStorage.setItem('ge_'+k,JSON.stringify(v));return v;},
  168. addButton: function(t,o,m,a) { // Base Function
  169. if(!a) a={};
  170. if(m) {
  171. var i,k=a.keys;
  172. if(!k||!k.length) k=['mousedown','mouseup'];
  173. for(i=0;i<k.length;i++) if(o[k[i]]) {o[k[i]].call(o,m);break;}
  174. }
  175. t=$(t);
  176. if(a.after) o.insertAfter(t.children(a.after));
  177. else if(a.before) o.insertBefore(t.children(a.before));
  178. else o.appendTo(t);
  179. return o;
  180. },
  181. addTButton: function(o,m) { // Add Toolbar Button
  182. var tb=$('div.edui-btn-toolbar').first();
  183. if(m) o.click(m);
  184. return o.appendTo($('<div class="edui-btn edui-btn-bold" unselectable="on" onmousedown="return false">').prependTo(tb));
  185. },
  186. addSButton: function(v) { // Add Big Button
  187. var b=$('<span class=poster_submit>').insertBefore('.poster_draft_status');
  188. b.label=$('<em>').html(v).appendTo(b).wrap('<a href="#" class="ui_btn ui_btn_m"><span>');
  189. return b;
  190. },
  191. addPopup: function(E,b,i) { // Obsoleted
  192. var p=utils.addRPopup(b,i);
  193. p.holder=E;
  194. return p;
  195. },
  196. addRPopup: function(b,i,c) { // Add popup for submit-like buttons
  197. var p=$('<div class=ge_panel_p title="">').prependTo(b).click(function(e){
  198. e.stopPropagation();
  199. //if(['A','BUTTON'].indexOf(e.target.tagName)>=0) e.preventDefault();
  200. }).hide();
  201. p.caret=$('<i class=ge_caret>').appendTo(p).html('<i>');
  202. p.panel=$('<div class=ge_panel>').appendTo(p);
  203. p.onclose=function(){
  204. p.hide();$(document).unbind('click',p.onclose);if(c) c(p);
  205. };
  206. p.onopen=function(){
  207. p.show();$(document).click(p.onclose);if(i) i(p);
  208. var l=Math.min(-50,$(document.body).innerWidth()-b.offset().left-p.panel.outerWidth());
  209. p.css({'margin-left':l});
  210. p.caret.css({left:b.width()/2-l-10});
  211. };
  212. p.ontoggle=function(e){
  213. e.preventDefault();
  214. if(p.is(':visible')) p.onclose(); else setTimeout(p.onopen,0);
  215. };
  216. b.click(p.ontoggle);
  217. return p;
  218. },
  219. addTPopup: function(b,i,c) { // Add popup for toolbar buttons
  220. var p=$('<div class="edui-dropdown-menu edui-popup" title="" style="display:block;top:44px;position:absolute;">').appendTo('.edui-dialog-container').click(function(e){
  221. e.stopPropagation();
  222. }).hide();
  223. p.caret=$('<div class="edui-popup-caret up" style="top:-8px;position:absolute;"></div>').appendTo(p);
  224. p.panel=$('<div class="edui-popup-body">').appendTo(p);
  225. p.onclose=function(){
  226. p.hide();$(document).unbind('click',p.onclose);if(c) c(p);
  227. };
  228. p.onopen=function(){
  229. p.show();$(document).click(p.onclose);if(i) i(p);
  230. var l=Math.max(-50,b.offset().left+b.width()-$(document.body).innerWidth());
  231. p.css({'right':l});
  232. p.caret.css({right:p.panel.outerWidth()+p.panel.offset().left-b.parent().offset().left-b.width()});
  233. };
  234. p.ontoggle=function(e){
  235. e.preventDefault();
  236. if(p.is(':visible')) p.onclose(); else setTimeout(p.onopen,0);
  237. };
  238. b.click(p.ontoggle);
  239. return p;
  240. },
  241. bindProp: function(obj,prop,key,def,func,evt) {
  242. obj.prop(prop,utils.getObj(key,def));
  243. if(!evt) evt=['change'];
  244. evt.forEach(function(i){obj.bind(i,function(e){utils.setObj(key,this[prop]);if(func) obj.each(function(i,o){func.call(o,e);});});});
  245. return obj;
  246. },
  247. shortcut:function(key,func){
  248. key=key.toLowerCase();
  249. var d=[];
  250. if(key.slice(-2)=='--') {d.push('-');key=key.slice(0,-2).split('-');}
  251. else key=key.split('-');
  252. if(key.indexOf('m')>=0||key.indexOf('meta')>=0) d.unshift('m');
  253. if(key.indexOf('s')>=0||key.indexOf('shift')>=0) d.unshift('s');
  254. if(key.indexOf('a')>=0||key.indexOf('alt')>=0) d.unshift('a');
  255. if(key.indexOf('c')>=0||key.indexOf('ctrl')>=0) d.unshift('c');
  256. key=key.join('-');
  257. if(func) shortcuts[key]=func; else delete shortcuts[key];
  258. },
  259. list: function(lkey,ikey,dnew,def) { // def===true: not null
  260. var t={};t.last=0;
  261. t.load=function(i,nosave){
  262. if(i==undefined) i=ikey?utils.getObj(ikey,0):0;
  263. if(i<0||!t.length) i=0; else if(i>=t.length) i=t.length-1;
  264. if(ikey&&!nosave) utils.setObj(ikey,i);
  265. t.cur=t.list[t.last=i];
  266. return t;
  267. };
  268. t.push=function(d){if(!d) d=dnew();t.list.push(d);t.save();return t.length-1;};
  269. t.pop=function(i){var o=t.list.splice(i,1)[0];t.save();t.load(i);return o;}
  270. t.save=function(){if(lkey) utils.setObj(lkey,t.list);if(ikey) utils.setObj(ikey,t.last);};
  271. t.list=lkey?utils.getObj(lkey,[]):[];
  272. Object.defineProperty(t,'length',{get:function(){return t.list.length;}});
  273. if(!t.length&&def) {if(def.concat) {t.list=def.concat();t.save();} else t.push();}
  274. return t;
  275. },
  276. getLink:function(t,o){
  277. o=o||{};
  278. var l=links[t];
  279. if(l) o.href=l;
  280. if(!o['target']) o.target='_blank';
  281. t=o.html||'';delete t.html;l=['<a'];
  282. for(i in o) l.push(i+'="'+o[i]+'"');
  283. return l.join(' ')+'>'+t+'</a>';
  284. },
  285. popup:{ // Popup Window
  286. dialog:null,
  287. className:'ge_popup',
  288. show:function(o){
  289. var t=this,d=t.dialog;
  290. t.hide();t.obj=o;
  291. d.className=o.className||'';
  292. d.classList.add(t.className);
  293. d.innerHTML=o.html;
  294. if(o.init) o.init(d);
  295. d.style.display='block';
  296. d.style.top=(innerHeight-d.offsetHeight)/2+'px';
  297. d.style.left=(innerWidth-d.offsetWidth)/2+'px';
  298. document.addEventListener('click',t._hide=t.hide.bind(this),false);
  299. },
  300. hide:function(){
  301. var t=this,o=t.obj,d=t.dialog;
  302. if(o) {
  303. if(o.dispose) o.dispose(d);
  304. d.innerHTML='';d.className=t.className;
  305. d.style.display='none';t.obj=null;
  306. document.removeEventListener('click',t._hide,false);
  307. }
  308. },
  309. },
  310. };
  311. document.addEventListener('keydown',function(e){
  312. if(e.target==document.body){
  313. var k=[],f;
  314. if(e.ctrlKey) k.push('c');
  315. if(e.altKey) k.push('a');
  316. if(e.shiftKey) k.push('s');
  317. if(e.metaKey) k.push('m');
  318. k.push(String.fromCharCode(e.keyCode));
  319. k=k.join('-').toLowerCase();
  320. if(f=shortcuts[k]) {e.preventDefault();f();}
  321. }
  322. },false);
  323. window.addEventListener('DOMContentLoaded',function(){
  324. var d=document.createElement('div');document.body.appendChild(d);
  325. d.addEventListener('click',function(e){e.stopPropagation();},false);
  326. utils.popup.dialog=d;
  327. utils.addStyle('\
  328. .ge_x{clear:both;}\
  329. .ge_popup{display:none;z-index:10006;font:normal normal 400 12px/18px 宋体;position:fixed;background:white;border:1px solid silver;box-shadow:5px 5px 7px #333;text-align:left;}\
  330. .ge_mask{background:rgba(0,0,0,0.6);position:fixed;top:0;bottom:0;left:0;right:0;z-index:1007;display:none;}\
  331. .ge_panel_p{position:relative;z-index:1006;}\
  332. .ge_panel{position:absolute;background:#eee;border:1px solid black;padding:10px;border-radius:5px;bottom:0;white-space:nowrap;}\
  333. .ge_caret,.ge_caret>i{position:absolute;border:solid;border-color:black transparent;border-width:8px 8px 0;z-index:889;}\
  334. .ge_caret>i{border-top-color:#eee;top:-9px;left:-8px;}\
  335. .ge_sbtn{background:#77f;color:white;border-radius:3px;border:1px solid;border:none;margin:2px;cursor:pointer;text-align:center;}\
  336. span.ge_sbtn{padding:2px 3px;}\
  337. .ge_disabled{background:gray;cursor:default;}\
  338. .ge_rsep{margin-right:10px;}\
  339. .ge_opt{padding:20px;border-radius:5px;}\
  340. .ge_opt fieldset{border:1px solid silver;border-radius:5px;padding:5px;}\
  341. .ge_opt textarea{min-height:100px;width:100%;}\
  342. ','ge_css');
  343. },false);
  344. var gkey='__ge_firefox',ff=unsafeWindow[gkey];
  345. if(!ff) ff=unsafeWindow[gkey]={};
  346. ff['utils']=utils;