QR-Plugins.IMG.WrapBBCode

plugins for Kaskus-QR, wrap all image link with img bbcode

目前为 2014-04-17 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name QR-Plugins.IMG.WrapBBCode
  3. // @namespace http://userscripts.org/scripts/show/QR-Plugins.IMG.AutoBBCode
  4. // @include *.kaskus.co.id/thread/*
  5. // @include *.kaskus.co.id/lastpost/*
  6. // @include *.kaskus.co.id/post/*
  7. // @include *.kaskus.co.id/group/discussion/*
  8. // @include *.kaskus.co.id/show_post/*
  9. // @version 0.1
  10. // @dtversion 1404140001
  11. // @timestamp 1351547543977
  12. // @qrversion 4.0
  13. // @description plugins for Kaskus-QR, wrap all image link with img bbcode
  14. // @author tuxie.forte;
  15. // @license (CC) by-nc-sa 3.0
  16. //
  17. // -!--latestupdate
  18. //
  19. //
  20. // v0.1 - 2014-04-14
  21. // init
  22. //
  23. // -/!latestupdate---
  24. // ==/UserScript==
  25. //
  26.  
  27. (function(){
  28. // Initialize Global Variables
  29. var gvar=function() {};
  30.  
  31. /*
  32. window.alert(new Date().getTime());
  33. */
  34. //========-=-=-=-=--=========
  35. gvar.__DEBUG__ = !1; // development
  36. //========-=-=-=-=--=========
  37.  
  38.  
  39. // this is where we re-initialize before we trigger start_Main()
  40. // any huge global var or loading any saved value may start in here too
  41. function init_start(){
  42. gvar.B = rSRC.getSetOf('button');
  43. gvar.tID = "reply-messsage";
  44.  
  45. // gvar.supportExt = '*';
  46. gvar.supportExt = 'gif,jpg,jpeg,png,pneg';
  47. start_Main();
  48. }
  49.  
  50. function handleClick(){
  51. var vBText = _TEXT.init();
  52. var re, isImg, ucok, textcontent = vBText.content;
  53. var extpat = ( gvar.supportExt == '*' ? "[\\w]+" : gvar.supportExt.split(",").join("|") );
  54. var imgStrRgx = "\\b(https?:\\/\\/(?:[a-z\\-]+\\.)+[a-z]{2,6}(?:\\/[^/#?\\n]+)+\\.(?:"+extpat+"))\\b";
  55.  
  56. isImg = new RegExp(imgStrRgx, "gi");
  57. re = new RegExp("(.[^\\n\\]\\[]+|^\\W|^)"+imgStrRgx+"([\\]\\[]+)?", "gim");
  58. clog( re );
  59.  
  60. if( re.test( textcontent ) ){
  61. // let parse..
  62. var parser = function parser(S, $1, $imglink, $3){
  63. var sbf='', prefix = (isDefined($1) && $1 ? $1.toUpperCase() : '');
  64. if( isUndefined($3) )
  65. $3 = '';
  66. if( isUndefined($1) )
  67. $1 = '';
  68.  
  69. clog("\nS="+S+';prefix='+prefix+';imglink='+$imglink+';$3='+$3+"\n");
  70.  
  71. if( $3 && (!prefix || (prefix == '[URL=' && $3 == ']')) ){
  72.  
  73. return S; // ignored
  74.  
  75. }
  76. else{
  77. if( isImg.test(trimStr(S)) )
  78. return S.replace(isImg, function(S, $$1){
  79. return '[IMG]'+$$1+'[/IMG]';
  80. });
  81. else
  82. return $1+'[IMG]'+($imglink ? $imglink : S)+'[/IMG]'+$3;
  83. }
  84. };
  85.  
  86. var tmp = textcontent.replace(re, parser);
  87. if( tmp != textcontent )
  88. vBText.set( tmp );
  89. }
  90. }
  91.  
  92.  
  93. // =====
  94. // START
  95. function start_Main(){
  96. var par = gID(gvar.qr_identity);
  97. var inp, span;
  98.  
  99. if( par ){
  100. // this span container needed if we have to wrap popup menu with absolute position
  101. span = createEl('span', {style:'display:inline-block'});
  102. Dom.add(span, par);
  103.  
  104. inp = createEl('img', {id:'btn_autoimgbbcode', 'src':gvar.B.txtflip_gif, style:'vertical-align:bottom;', alt:'[imgautobbcode]', title:'IMG.AutoBBCode'});
  105. _o('click', inp, function(e){return handleClick(e)} );
  106. Dom.add(inp, span);
  107. }
  108. }
  109.  
  110.  
  111.  
  112. // -
  113. // -
  114. // -
  115. // -
  116. //=========
  117. // code below should adapting current QR Engine for this plugins works
  118. // leave code below as wot it is, as long you know what todo
  119. //========= Common Functions && Global Var Init ====
  120. // static routine
  121. function isDefined(x) { return !(x == null && x !== null); }
  122. function isUndefined(x) { return x == null && x !== null; }
  123. function isString(x) { return (typeof(x)!='object' && typeof(x)!='function'); }
  124. function trimStr(x) { return x.replace(/^\s+|\s+$/g,""); };
  125.  
  126. function _o(m,e,f){Dom.Ev(e,m,function(e){typeof(f)=='function'?f(e):void(0)});}
  127. function gID(x) { return document.getElementById(x) }
  128. function addClass(cName, Obj){
  129. if(cName=="") return;
  130. var neocls = (Obj.className ? Obj.className : '');
  131. if(neocls.indexOf(cName)!=-1) return;
  132. neocls+=(neocls!=''?' ':'')+cName;
  133. Obj.setAttribute('class', neocls);
  134. }
  135. function removeClass(cName, Obj){
  136. if(cName=="") return;
  137. var neocls = (Obj.className ? Obj.className : '');
  138. neocls = trimStr ( neocls.replace(cName,"") ); // replace and trim
  139. Obj.setAttribute('class', neocls);
  140. }
  141. function SimulateMouse(elem,event,preventDef) {
  142. if(typeof(elem)!='object') return;
  143. var evObj = document.createEvent('MouseEvents');
  144. preventDef=(isDefined(preventDef) && preventDef ? true : false);
  145. evObj.initEvent(event, preventDef, true);
  146. try{elem.dispatchEvent(evObj);}
  147. catch(e){}
  148. }
  149. function createEl(type, attrArray, html){
  150. var node = document.createElement(type);
  151. for (var attr in attrArray)
  152. if (attrArray.hasOwnProperty(attr))
  153. node.setAttribute(attr, attrArray[attr]);
  154. if(html) node.innerHTML = html;
  155. return node;
  156. }
  157.  
  158. // Get Elements
  159. var $D=function (q, root, single) {
  160. if (root && typeof root == 'string') {
  161. root = $D(root, null, true);
  162. if (!root) { return null; }
  163. }
  164. if( !q ) return false;
  165. if ( typeof q == 'object') return q;
  166. root = root || document;
  167. if (q[0]=='/' || (q[0]=='.' && q[1]=='/')) {
  168. if (single) { return document.evaluate(q, root, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; }
  169. return document.evaluate(q, root, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  170. }
  171. else if (q[0]=='.') { return root.getElementsByClassName(q.substr(1)); }
  172. else { return root.getElementById( (q[0]=='#' ? q.substr(1):q.substr(0)) ); }
  173. return root.getElementsByTagName(q);
  174. };
  175. // utk add - remove element
  176. var Dom = {
  177. g: function(el) {
  178. if(!el) return false;
  179. return ( isString(el) ? document.getElementById(el) : el );
  180. },
  181. add: function(el, dest) {
  182. var el = this.g(el);
  183. var dest = this.g(dest);
  184. if(el && dest) dest.appendChild(el);
  185. },
  186. remove: function(el) {
  187. var el = this.g(el);
  188. if(el && el.parentNode)
  189. el.parentNode.removeChild(el);
  190. },
  191. Ev: function() {
  192. if (window.addEventListener) {
  193. return function(el, type, fn, ph) {
  194. if(typeof(el)=='object')
  195. this.g(el).addEventListener(type, function(e){fn(e);}, (isUndefined(ph) ? false : ph));
  196. };
  197. }else if (window.attachEvent) {
  198. return function(el, type, fn) {
  199. var f = function() { fn.call(this.g(el), window.event); };
  200. this.g(el).attachEvent('on' + type, f);
  201. };
  202. }
  203. }()
  204. };
  205.  
  206. var _TEXT = {
  207. e : null, eNat : null,
  208. content : "",
  209. cursorPos : [],
  210. last_scrollTop: 0,
  211. init: function() {
  212. this.eNat = gID(gvar.tID);
  213. this.content = this.eNat.value;
  214. this.cursorPos = _TEXT.rearmPos(); // [start, end]
  215. this.last_scrollTop = gID(gvar.tID).scrollTop; // last scrolltop pos
  216. return this;
  217. },
  218. rearmPos: function(){ return [this.getCaretPos(), gID(gvar.tID).selectionEnd]; },
  219. subStr: function(start, end){ return this.content.substring(start, end);},
  220. set: function(value){
  221. gID(gvar.tID).value = this.content = value;
  222. _TEXT.setRows_Elastic();
  223. _TEXT.init();
  224.  
  225. },
  226. wrapValue : function(tag, title){
  227. var st2, start=this.cursorPos[0], end=this.cursorPos[1],bufValue;
  228. tag = tag.toUpperCase();
  229. bufValue = this.subStr(0, start) +
  230. '['+tag+(title?'='+title:'')+']' +
  231. (start==end ? '' : this.subStr(start, end)) +
  232. '[/'+tag+']' + this.subStr(end, this.content.length);
  233. this.set(bufValue);
  234. st2 = (start + ('['+tag+(title?'='+title:'')+']').length);
  235. this.setCaretPos( st2, st2 + this.subStr(start, end).length );
  236. if(this.overflow!='hidden') gID(gvar.tID).scrollTop = (this.last_scrollTop+1);
  237. return bufValue;
  238. },
  239. add: function(text){ // used on fetch post only
  240. var newline = '\n\n';
  241. if( gID(gvar.tID).value != "" )
  242. this.content+= newline;
  243. gID(gvar.tID).value = ( this.content + text );
  244. setTimeout(function(){
  245. _TEXT.lastfocus();
  246. }, 200);
  247. },
  248. // ptpos stand to puretext position [start, end]
  249. setValue : function(text, ptpos){
  250. var start=this.cursorPos[0], end=this.cursorPos[1];
  251. if(isUndefined(ptpos)) ptpos=[text.length,text.length];
  252. if(start!=end) {
  253. this.replaceSelected(text,ptpos);
  254. return;
  255. }
  256. var bufValue = this.subStr(0, start) + text + this.subStr(start, this.content.length);
  257. this.set(bufValue);
  258. // fix chrome weird
  259. this.setCaretPos( (start + ptpos[0]), (start+ptpos[1]) );
  260. if(_TEXT.overflow!='hidden') gID(gvar.tID).scrollTop = (this.last_scrollTop+1);
  261. return bufValue;
  262. },
  263. replaceSelected : function(text, ptpos){
  264. var start=this.cursorPos[0], end=this.cursorPos[1];
  265. if(start==end) return;
  266. var bufValue = this.subStr(0, start) + text + this.subStr(end, this.content.length);
  267. this.set(bufValue);
  268. this.setCaretPos( (start + ptpos[0]), (start+ptpos[1]) );
  269. if( _TEXT.overflow!='hidden') gID(gvar.tID).scrollTop = (this.last_scrollTop+1);
  270. },
  271. pracheck: function(foc){
  272. if( isUndefined(foc) )
  273. foc = true;
  274. _TEXT.setElastic(gvar.maxH_editor);
  275. if( gID(gvar.tID).value !="" )
  276. gID('clear_text').style.setProperty('display', 'block');
  277. else
  278. gID('clear_text').style.setProperty('display', 'none');
  279. if(foc) setTimeout(function(){
  280. _TEXT.focus();
  281. }, 200);
  282. },
  283. focus: function(){
  284. gID(gvar.tID).focus()
  285. },
  286. lastfocus: function (){
  287. var eText, nl, pos, txt = String(gID(gvar.tID).value); // use the actual content
  288. pos = txt.length;
  289. nl = txt.split('\n');
  290. nl = nl.length;
  291. pos+= (nl * 2);
  292. eText = gID(gvar.tID);
  293. if( eText.setSelectionRange ) {
  294. _TEXT.focus();
  295. eText.setSelectionRange(pos,pos);
  296. }
  297. setTimeout(function(){ _TEXT.focus() } , 310);
  298. },
  299. getSelectedText : function() {
  300. return (this.cursorPos[0]==this.cursorPos[1]? '': this.subStr(this.cursorPos[0], this.cursorPos[1]) );
  301. },
  302. getCaretPos : function() {
  303. var CaretPos = 0;
  304. //Mozilla/Firefox/Netscape 7+ support
  305. if(gID(gvar.tID))
  306. if (gID(gvar.tID).selectionStart || gID(gvar.tID).selectionStart == '0')
  307. CaretPos = gID(gvar.tID).selectionStart;
  308. return CaretPos;
  309. },
  310. setCaretPos : function (pos,end){
  311. if(isUndefined(end)) end = pos;
  312. if(gID(gvar.tID).setSelectionRange) { // Firefox, Opera and Safari
  313. this.focus();
  314. gID(gvar.tID).setSelectionRange(pos,end);
  315. }
  316. },
  317. setElastic: function(max,winrez){
  318. var a, tid=gvar.tID;
  319. function setCols_Elastic(max){
  320. var a=gID(tid); a.setAttribute("cols", Math.floor(a.clientWidth/7));
  321. var w = Math.floor(a.clientWidth/7);
  322. _TEXT.setRows_Elastic(max)
  323. }
  324. a= gID(tid) || gID(gvar.tID);
  325. _TEXT.oflow='hidden';
  326. a.setAttribute('style','visibility:hidden; overflow:'+_TEXT.oflow+';letter-spacing:0;line-height:14pt;'+(max?'max-height:'+(max-130)+'pt;':''));
  327. if( !winrez ) gID(gvar.tID).keyup(function(){ setCols_Elastic(max) });
  328. setCols_Elastic(max);
  329. },
  330. setRows_Elastic: function(max){
  331. var a = gID(gvar.tID), c=a.cols, b=a.value.toString(), h;
  332. b=b.replace(/(?:\r\n|\r|\n)/g,"\n");
  333. for(var d=2,e=0,f=0;f<b.length;f++){
  334. var g=b.charAt(f);e++;if(g=="\n"||e==c){d++;e=0}
  335. }
  336. h=(d*14); a.setAttribute("rows",d); a.style.height=h+"pt";
  337. _TEXT.oflow = (max && (d*14>(max-130)) ? 'auto':'hidden');
  338. a.style.setProperty('overflow', _TEXT.oflow, 'important');
  339. gID(gvar.tID).style.setProperty('visibility', 'visible');
  340. }
  341. };
  342.  
  343.  
  344. // ----my ge-debug--------
  345. function show_alert(msg, force) {
  346. if(arguments.callee.counter) { arguments.callee.counter++; } else { arguments.callee.counter=1; }
  347. GM_log('('+arguments.callee.counter+') '+msg);
  348. if(force==0) { return; }
  349. }
  350. function clog(msg) {
  351. if(!gvar.__DEBUG__) return;
  352. show_alert(msg);
  353. }
  354.  
  355.  
  356.  
  357. // main resource
  358. var rSRC = {
  359. getSetOf: function(type){
  360. if(isUndefined(type)) return false;
  361. switch(type){
  362. case "button":
  363. return {
  364. txtflip_gif : ""
  365. +"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAASCAAAAAB+u6HMAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB94EEBANFPIrL+AAAABNSURBVBjTY/zPgAmYsIgxsDBUX0YT0m1lQeZuYrjMoFvFwMDCwCDmDBNczsDAcOWVOAMLA4NYJIruyzgsGiqCLAwMV/zQAoSBkejwBACJzwu9lnUAQAAAAABJRU5ErkJggg=="
  366.  
  367. };
  368. break;
  369. }
  370. }
  371.  
  372. };
  373. // -end static
  374. //=========
  375.  
  376. function init(){
  377. gvar.qr_identity= 'qr_plugins_container';
  378. gvar.try_wait = 0;
  379. gvar.try_max = 20;
  380. gvar.sITry_wait= null;
  381.  
  382. wait_for_qr();
  383. }
  384.  
  385. // make sure QR DOM is finished loaded
  386. function wait_for_qr(){
  387. if( gvar.try_wait<gvar.try_max ){
  388. if( !gID(gvar.qr_identity) ){
  389. clog('IMG.AutoBBCode waiting.. ');
  390. gvar.try_wait++;
  391. gvar.sITry_wait = window.setTimeout(function() { wait_for_qr() }, 500);
  392. }else{
  393. clearTimeout( gvar.sITry_wait );
  394. init_start();
  395. }
  396. }
  397. }
  398.  
  399. // ------
  400. init();
  401. // ------
  402.  
  403. })()
  404. /* tF. */