QR-Plugins.IMG.WrapBBCode

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

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