Guest User

Untitled

a guest
Nov 25th, 2016
595
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name LOR TreeView
  3. // @description Make tree view for LOR threads (with jQuery)
  4. // @exclude http*://*linux.org.ru/forum/*/
  5. // @exclude http*://*linux.org.ru/news/*/
  6. // @exclude http*://*linux.org.ru/gallery/*/
  7. // @exclude http*://*linux.org.ru/polls/*/
  8. // @include http*://*linux.org.ru/forum/*/*
  9. // @include http*://*linux.org.ru/news/*/*
  10. // @include http*://*linux.org.ru/gallery/*/*
  11. // @include http*://*linux.org.ru/polls/*/*
  12. // @require https://www.linux.org.ru/webjars/jquery/1.12.3/jquery.min.js
  13. // @grant none
  14. // @UpdateURL http://userscripts.org/scripts/source/15985.user.js
  15. // @version 7.16.1
  16. // ==/UserScript==
  17. //
  18. // License: GNU GPL v3 or later
  19. // Copyright (C) 2012 sdio
  20. //
  21. // The JavaScript code in this page is free software: you can
  22. // redistribute it and/or modify it under the terms of the GNU
  23. // General Public License (GNU GPL) as published by the Free Software
  24. // Foundation, either version 3 of the License, or (at your option)
  25. // any later version. The code is distributed WITHOUT ANY WARRANTY;
  26. // without even the implied warranty of MERCHANTABILITY or FITNESS
  27. // FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
  28. //
  29. // As additional permission under GNU GPL version 3 section 7, you
  30. // may distribute non-source (e.g., minimized or compacted) forms of
  31. // that code without the copy of the GNU GPL normally required by
  32. // section 4, provided you include this license notice and a URL
  33. // through which recipients can access the Corresponding Source.
  34. //
  35. // Author: sdio (http://www.linux.org.ru/people/sdio/profile)
  36. // Contributed by:
  37. // kodx ( http://kodx.org )
  38. // ZaWertun ( http://www.linux.org.ru/people/ZaWertun/profile )
  39. // TikName ( https://www.linux.org.ru/people/TikName/profile )
  40. //
  41. //
  42.  
  43. // change color of links
  44. var ALTERLINKS = 1;
  45. // use quick answer form
  46. var USE_QUICK_ANSWER = 1;
  47.  
  48. var THEME;
  49. // set the default theme in case autodetect fail
  50. THEME = 'tango';
  51. //THEME = 'white'
  52. //THEME = 'black';
  53.  
  54. //----------------------------------------------------------------
  55. var COLOR = new Array;
  56. COLOR['white'] = 'black';
  57. COLOR['white2'] = 'black';
  58. COLOR['black'] = 'white';
  59. COLOR['tango'] = '#729fcf';
  60. COLOR['swamp'] = 'black';
  61.  
  62. // Length of the BACKGROUNDS array may be any, so change it as you want
  63. var BACKGROUNDS = new Array;
  64. BACKGROUNDS['white'] = ['#ccf', '#ffc', '#cfc', '#fcc', '#cff', '#fcf', '#ccc'];
  65. BACKGROUNDS['white2'] = ['#ccf', '#ffc', '#cfc', '#fcc', '#cff', '#fcf', '#ccc'];
  66. BACKGROUNDS['black'] = ['#006', '#330', '#303', '#033', '#300', '#030', '#333'];
  67. BACKGROUNDS['tango'] = ['#452830', '#284542', '#283145', '#452845'];
  68. BACKGROUNDS['swamp'] = ['#C0C3B1', '#B0B8A1', '#A0A895', '#909580'];
  69.  
  70. var POPUPBG = new Array;
  71. POPUPBG['white'] = 'yellow';
  72. POPUPBG['white2'] = 'yellow';
  73. POPUPBG['black'] = 'grey';
  74. POPUPBG['tango'] = 'grey';
  75. POPUPBG['swamp'] = 'yellow';
  76.  
  77. var POPUPBRD = new Array;
  78. POPUPBRD['white'] = 'black';
  79. POPUPBRD['white2'] = 'black';
  80. POPUPBRD['black'] = 'white';
  81. POPUPBRD['tango'] = 'white';
  82. POPUPBRD['swamp'] = 'black';
  83.  
  84. // Indentation per reply level
  85. const INDENT = '10px';
  86. const DAYS = 3;
  87. const COOKIENAME = "TreeView";
  88.  
  89. var options = {
  90. // target: '#quickanswerdiv',
  91. // post-submit callback
  92. success: showResponse,
  93. cache: false
  94. };
  95.  
  96. var jq;
  97. var st;
  98. jq = $;
  99. st = setTimeout;
  100.  
  101. function ctrl_enter(e, form) {
  102. if (((e.keyCode == 13) || (e.keyCode == 10)) && (e.ctrlKey)) {
  103. jq("#quickanswerform").ajaxForm(options).submit();
  104. }
  105. }
  106.  
  107. function jump(link) {
  108. return 1;
  109. }
  110.  
  111. function image_onload(elem) {
  112. var width = elem.naturalWidth;
  113. if (width < 320) {
  114. elem.style.width = '';
  115. }
  116. }
  117. window.onbeforeunload = null;
  118.  
  119. var msgs = -1;
  120. var thread_id;
  121. var topic = jq('div.messages article[id*="topic-"]');
  122. if (topic.length) {
  123. thread_id = topic.attr('id').split('-')[1];
  124. } else {
  125. alert('Error: can not detect thread ID.');
  126. }
  127.  
  128. var cnt = getCounter(thread_id, 0);
  129. var newid = new Array;
  130.  
  131.  
  132. jq('link').each(function() {
  133. var found = this.href.match(/\/([^/]*)\/combined\.css/);
  134. if (found) {
  135. THEME = found[0].split('/')[1];
  136. if (THEME == 'tango') {
  137. var subtheme = readCookie("style_selected");
  138. if (subtheme == 'tango-swamp') {
  139. THEME = 'swamp';
  140. }
  141. }
  142. }
  143. });
  144.  
  145.  
  146. jq('<div id="popupContact"><br><h2><span id="popupMsgs">0</span> new messages</h2><br></div>').hide().appendTo('body');
  147. jq("#popupContact").css({
  148. "background-color": POPUPBG[THEME],
  149. "padding": "10px",
  150. "border": "1px solid " + POPUPBRD[THEME],
  151. "position": "fixed",
  152. "top": (document.documentElement.clientHeight - 200) / 2,
  153. "left": (document.documentElement.clientWidth - 300) / 2
  154. });
  155.  
  156. jq('<div id="popupPreview"></div>').hide().appendTo('body');
  157.  
  158. jq("#popupPreview").css({
  159. "text-align": "left",
  160. "background-color": POPUPBG[THEME],
  161. "padding": "5px",
  162. "border": "1px solid " + POPUPBRD[THEME],
  163. "position": "fixed",
  164. "top": (document.documentElement.clientHeight) / 5,
  165. "left": 50
  166. });
  167.  
  168. jq('.msg-container').css('margin-left', '0.5em');
  169.  
  170. //start: Сообщить модератору (based on http://infoman.name/userscripts)
  171.  
  172. jq.GMReport = {
  173. topicnum: null
  174. }
  175.  
  176. GMReportFunctions = {
  177. // Save topic number in cache
  178. savetopicnum: function() {
  179. createCookie("topicnum", jq.GMReport.topicnum, DAYS)
  180. createCookie("topictime", new Date().getTime().toString(), DAYS);
  181. },
  182.  
  183. fetchtopicnum: function() {
  184. jq.GMReport.topicnum = -1;
  185. var req = new XMLHttpRequest();
  186. req.open('GET', location.protocol + '//www.linux.org.ru/group.jsp?group=4068', true);
  187. req.onreadystatechange = function(e) {
  188. if (req.readyState == 4) {
  189. if (req.status == 200) {
  190. jq(req.responseText).find("img[alt='Прикреплено']").each(function() {
  191. var link = jq(this).next("a");
  192. if (/Ссылки.*некор/i.test(link.html())) {
  193. jq.GMReport.topicnum = /linux-org-ru\/(\d+)/.exec(link.attr("href"))[1];
  194. GMReportFunctions.savetopicnum();
  195. }
  196. });
  197. } else
  198. alert("Cannot get reports topic number");
  199. }
  200. }
  201. req.send(null);
  202. },
  203.  
  204. // Get topic number for sending reports
  205. gettopicnum: function() {
  206. if (jq.GMReport.topicnum == null) {
  207. var num = readCookie("topicnum");
  208. var time = new Number(readCookie("topictime"));
  209. var cur = new Date().getTime();
  210. if ((num != null) && ((cur - time) < 7200000))
  211. jq.GMReport.topicnum = num;
  212. else
  213. GMReportFunctions.fetchtopicnum();
  214. }
  215. if (jq.GMReport.topicnum == -1)
  216. st(GMReportFunctions.gettopicnum, 100);
  217. if (jq.GMReport.topicnum > 0)
  218. letsGo();
  219. }
  220. }
  221.  
  222. GMReportFunctions.gettopicnum();
  223.  
  224. // All your GM code must be inside this function
  225. function letsGo() {
  226. jq("div.reply").each(function() {
  227. var div = jq(this);
  228. if (/^[^Ответ]/.test(div.html()))
  229. div.append("[<a class='lor-report-msg' href='javascript:{/*Сообщить модератору (страница не будет перезагружена)*/}'>Сообщить модератору</a>]");
  230. });
  231.  
  232.  
  233. jq("a.lor-report-msg").click(function() {
  234. // hack: why .unbind() doesn't work
  235. if (jq(this).html() == "Просмотреть")
  236. return true;
  237.  
  238. var comment = prompt("Please provide a comment about this message", "Нацпол");
  239. if (comment === null)
  240. return false;
  241. // Constructing message for posting
  242. var msgtext = null;
  243. var reportlink = jq(this);
  244. var url1 = reportlink.parent().parent().parent().parent().find("div.msg_body h1 a:first");
  245. if (url1.length == 0)
  246. url1 = reportlink.parent().find("li:nth-child(2) a:first");
  247.  
  248. if (!msgtext)
  249. msgtext = comment + " : " + url1.get(0).href;
  250.  
  251. var message = {
  252. csrf: /CSRF_TOKEN="(.+)"/.exec(document.cookie)[1],
  253. topic: jq.GMReport.topicnum,
  254. title: "",
  255. msg: msgtext
  256. }
  257. jq.post(location.protocol + "//www.linux.org.ru/add_comment.jsp", message, function(data) {
  258. var allmsgs = jq(data).find("article.msg");
  259. var reportnum = /\d+/.exec(allmsgs.eq(allmsgs.length - 1).attr("id"))[0];
  260. reportlink.unbind().attr("href", location.protocol + "//www.linux.org.ru/jump-message.jsp?msgid=" + jq.GMReport.topicnum + "&cid=" + reportnum).html("Просмотреть");
  261. })
  262. });
  263. }
  264.  
  265. //end: Сообщить модератору
  266.  
  267. function createCookie(name, value, days) {
  268. var expires;
  269. if (days) {
  270. var date = new Date();
  271. date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
  272. expires = "; expires=" + date.toGMTString();
  273. } else
  274. expires = "";
  275. document.cookie = name + "=" + value + expires + "; path=/";
  276. }
  277.  
  278. function readCookie(name) {
  279. var nameEQ = name + "=";
  280. var ca = document.cookie.split(';');
  281. for (var i = 0; i < ca.length; i++) {
  282. var c = ca[i];
  283. while (c.charAt(0) == ' ') c = c.substring(1, c.length);
  284. if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
  285. }
  286. return null;
  287. }
  288.  
  289. function jq_get(url, callback) {
  290. var data = {};
  291. var param = url.split('?')[1];
  292. var url = url.split('?')[0];
  293. if (param) {
  294. var params = param.split('&');
  295. for (var i = 0; i < params.length; i++) {
  296. var key = params[i].split('=')[0];
  297. var val = params[i].split('=')[1];
  298. switch (key) {
  299. case 'msgid':
  300. data[key] = val;
  301. break;
  302. case 'page':
  303. data[key] = val;
  304. break;
  305. case 'filter':
  306. data[key] = val;
  307. break;
  308. }
  309. }
  310. }
  311. jq.ajaxSetup({ cache: false });
  312. jq.get(url, data, callback);
  313. }
  314.  
  315.  
  316.  
  317. //get from Cookie or GM stored thread's message counter
  318. function getCounter(msg_id, update) {
  319. var count = null;
  320. var str = readCookie(COOKIENAME);
  321. if (str) {
  322. var flag = 0;
  323. var d = new Date();
  324. var nowtime = d.getTime();
  325. var newarr = new Array;
  326. var arr = str.split("_");
  327. var j;
  328. var k = 0;
  329. newarr[k++] = "";
  330. for (var i = 1; i < arr.length; i += 3) {
  331. if (arr[i] == msg_id) {
  332. // found
  333. j = i + 1;
  334. count = arr[j];
  335. } //if
  336. j = i + 2;
  337. if (arr[j] > nowtime) {
  338. j = i;
  339. newarr[k++] = arr[j++];
  340. newarr[k++] = arr[j++];
  341. newarr[k++] = arr[j++];
  342. } else {
  343. flag = 1; // will purge expired records
  344. } //if
  345.  
  346. } //for
  347. if (flag) {
  348. str = newarr.join("_");
  349. createCookie(COOKIENAME, str, DAYS);
  350. }
  351. } //if(str)
  352. if (!count) {
  353. if (update) {
  354. count = jq("div.comment article.msg").length;
  355. } else {
  356. count = 0;
  357. }
  358. }
  359. return count;
  360. }
  361.  
  362. function setCounter(msg_id, value) {
  363. var d = new Date();
  364. var expireat = d.getTime();
  365. expireat += DAYS * 24 * 60 * 60 * 1000;
  366.  
  367. var flag = 0;
  368. var str = readCookie(COOKIENAME);
  369. if (str) {
  370. var arr = str.split("_");
  371. for (var i = 1; i < arr.length; i += 3) {
  372. if (arr[i] == msg_id) {
  373. // found
  374. arr[++i] = value;
  375. arr[++i] = expireat;
  376. flag = 1;
  377. break;
  378. }
  379. }
  380. } else {
  381. str = "";
  382. }
  383.  
  384. if (flag) {
  385. // updated
  386. str = arr.join("_");
  387. } else {
  388. // new one
  389. str = str + "_" + msg_id + "_" + value + "_" + expireat;
  390. }
  391. createCookie(COOKIENAME, str, DAYS);
  392. }
  393.  
  394. //
  395. // callback function on UPDATE action
  396. //
  397. function onAjaxSuccess(data) {
  398. // data is html returned by server
  399. var up_div = jq(data).find('div.comment article.msg');
  400.  
  401. // number of messages received from server
  402. var newmsgs = up_div.length;
  403.  
  404. // [newmsgs > msgs] means that there are new messages
  405. if (newmsgs > msgs) {
  406. newid.length = 0;
  407. if (msgs > 0) {
  408. up_div.slice(msgs, newmsgs).each(doindent);
  409. } else {
  410. up_div.each(doindent);
  411. }
  412. // update message counter
  413. jq("#popupMsgs").text(newmsgs - msgs);
  414. msgs = jq('div.comment article.msg').length;
  415. setCounter(thread_id, msgs);
  416. cnt = msgs;
  417.  
  418. jq('a._new_').remove();
  419. addNavigateLinks(newid);
  420. if (document.getElementById(newid[0])) document.getElementById(newid[0]).scrollIntoView();
  421. newid.length = 0;
  422.  
  423. } else {
  424. // no news
  425. // drop temp data
  426. jq("#popupMsgs").text('0');
  427. }
  428. jq("#popupContact").show();
  429. st('$("#popupContact").hide();', 3000);
  430. }
  431.  
  432.  
  433. function quickAnswer(elem) {
  434. var topic;
  435. var replyto;
  436. var href = elem.search;
  437. var session = /CSRF_TOKEN="(.+)"/.exec(document.cookie)[1];
  438.  
  439. var seltxt;
  440. try {
  441. seltxt = window.getSelection().toString();
  442. } catch (err) {
  443. alert(err);
  444. }
  445. if (seltxt) {
  446. seltxt = '> ' + seltxt + "\n";
  447. }
  448.  
  449. jq("#quickanswerdiv").remove();
  450.  
  451. var formhtml1 = '<form id="quickanswerform" method="POST" action="add_comment.jsp"> <input type="hidden" name="csrf" value="' + session + '"/> <input type="hidden" name="topic" value="';
  452. var formhtml2 = '<input type="text" name="title" size="73" value=""/><br> <textarea name="msg" cols="70" rows="10" onkeypress="return ctrl_enter(event, this.form);">' + seltxt + '</textarea><br> <input type="hidden" name="texttype" value="0"/><br><input type="submit" value="Отправить"/><input type="submit" value="Предпросмотр" name="preview"/></form>';
  453.  
  454. if (href.match(/replyto=/)) {
  455. topic = href.replace(/^.*topic=(\d+).*$/, "$1");
  456. replyto = href.replace(/^.*replyto=(\d+).*$/, "$1");
  457. formhtml1 = formhtml1 + topic + '"/> <input type="hidden" name="replyto" value="' + replyto + '"/>';
  458. } else {
  459. topic = href.replace(/^.*topic=(\d+).*$/, "$1");
  460. formhtml1 = formhtml1 + topic + '"/>';
  461. }
  462.  
  463. jq(elem).parent().append('<div id="quickanswerdiv">' + formhtml1 + formhtml2 + '</div>');
  464.  
  465. jq("#quickanswerform").ajaxForm(options);
  466.  
  467. jq("textarea[name=msg]").focus();
  468.  
  469. }
  470.  
  471.  
  472. function showResponse(responseText, statusText) {
  473. // data is html returned by server
  474. var h1txt = jq(responseText).find('div.error').text();
  475. if (h1txt) {
  476. alert(h1txt);
  477. return;
  478. }
  479. h1txt = jq(responseText).find('p:contains("Ваше сообщение")').text();
  480. if (h1txt) {
  481. var rmsg = jq(responseText).find('div.messages');
  482. if (rmsg) {
  483. jq("#popupPreview").get(0).innerHTML = rmsg.get(rmsg.length - 1).innerHTML;
  484. jq("#popupPreview").show();
  485. st('$("#popupPreview").hide();', 5000);
  486. }
  487. } else {
  488. //up_div.empty();
  489. jq("#quickanswerdiv").remove();
  490. jq_get(document.location.href, onAjaxSuccess);
  491. }
  492. }
  493.  
  494. //add a link with "text", "url" and "id" after <<elem>> html object.
  495. function addNavButton(elem, text, url, cls) {
  496. var newA = document.createElement("a");
  497. newA.href = url;
  498. newA.className = cls;
  499. newA.textContent = text;
  500. newA.style.paddingLeft = "20px !important";
  501. newA.style.color = COLOR[THEME] + '!important';
  502. elem.appendChild(document.createTextNode(' '));
  503. elem.appendChild(newA);
  504. }
  505.  
  506. //add navigation links (First/Next/Prev/Last) for recently added messages
  507. function addNavigateLinks(msg_array) {
  508. var len = msg_array.length;
  509. //Add navigation buttons for new messages
  510. for (var i = 0; i < len; i++) {
  511. var msgTD = jq("#" + msg_array[i] + " div.title").get(0);
  512. if (msgTD) {
  513. //next message
  514. var nText = "[Next new]";
  515. var n = i + 1;
  516. if (n >= len) {
  517. n = 0;
  518. nText = "[First new]";
  519. var titleA = jq("div.title").get(0);
  520. if (titleA) {
  521. addNavButton(titleA,
  522. nText,
  523. 'javascript:document.getElementById("' + msg_array[n] + '").scrollIntoView()', "sign_more _new_"
  524. );
  525. }
  526. }
  527. addNavButton(msgTD, nText, 'javascript:document.getElementById("' + msg_array[n] + '").scrollIntoView()', "sign_more _new_");
  528.  
  529. //previous message
  530. var pText = "[Prev new]";
  531. var p = i - 1;
  532. if (p < 0) {
  533. p = len - 1;
  534. pText = "[Last new]";
  535. }
  536. addNavButton(msgTD,
  537. pText,
  538. 'javascript:document.getElementById("' + msg_array[p] + '").scrollIntoView()', "sign_more _new_"
  539. );
  540. }
  541. }
  542. }
  543.  
  544. // ---------------------------------------------------------------------
  545. function doindent(index) {
  546. this.setAttribute("treelevel", "0"); // initial indent level
  547. // this.style.paddingBottom = "1px"; // style
  548. // this.style.marginBottom = "4px"; // style
  549. var root;
  550.  
  551. // store new id in array
  552. if ((msgs + index + 1) >= cnt) {
  553. newid.push(this.id);
  554. }
  555.  
  556. root = jq("div.comment").get(0);
  557.  
  558. // remove subject
  559. // jq("h2", this).html('<hr>');
  560.  
  561. var nick = jq("div.sign a:first", this).text();
  562. if (nick) {
  563. jq("div.title", this).append(' <a class = "sign_more" href="' + location.protocol + '//www.linux.org.ru/show-replies.jsp?output=rss&nick=' + nick + '" >[' + nick + ' events]</a>');
  564. }
  565. // append [update page] link
  566. jq("div.title", this).append(' <a href="#" class="sign_more updatepage">[update page]</a>');
  567. jq('a.updatepage', this).click(function(event) {
  568. jq_get(document.location.href, onAjaxSuccess);
  569. event.preventDefault();
  570. });
  571. var ign = jq('span.user-remark:contains("###"):first', this);
  572. if (ign.length) {
  573. ign.parent().parent().hide();
  574. jq("div.title", this).append('<a href="javascript:{}" class="vtoggle">[show/hide]</a>');
  575. jq('a.vtoggle', this).click(function(event) {
  576. jq('div[class*="msg_body"]:first', jq(this).parent().parent()).toggle();
  577. event.preventDefault();
  578. });
  579.  
  580. }
  581.  
  582. // do all links colored black
  583. if (ALTERLINKS) {
  584. if (THEME != 'tango' || THEME != 'swamp') {
  585. jq("a", this).css('cssText', 'color: ' + COLOR[THEME] + ' !important');
  586. }
  587. }
  588. jq(".sign", this).css('cssText', 'text-align: left');
  589.  
  590. // enumerate message
  591. jq("div.title", this).prepend('[' + (msgs + index + 1) + '] ');
  592. // jq("div.title a:first", this).each(function () {
  593. // this.setAttribute("class", "counter");
  594. // });
  595.  
  596. // quick answer
  597. if (USE_QUICK_ANSWER) {
  598. jq('a:contains("Ответить на это сообщение")', this).click(function(event) {
  599. event.preventDefault();
  600. quickAnswer(this);
  601. });
  602. }
  603.  
  604. // is a message answer to other (non root) message?
  605. var a = jq('div.title a[data-samepage="samePage"]', this);
  606. if (a.length) {
  607. // #Id of reply message <DIV>
  608. var idr = a.attr('href').split('cid=')[1];
  609. idr = 'comment-' + idr;
  610. // "parent" message
  611. var idr_msg = document.getElementById(idr);
  612. // child's indent level
  613. var idr_level = idr_msg.getAttribute("treelevel");
  614. idr_level++;
  615.  
  616. // save child's indent level
  617. this.setAttribute("treelevel", idr_level);
  618.  
  619. // move child to parent
  620. idr_msg.appendChild(this);
  621. // choose color accordingly to indent level
  622. var bgcolor = BACKGROUNDS[THEME][idr_level % BACKGROUNDS[THEME].length] + ' !important';
  623. // set background color to .title and .body
  624. jq('article#' + this.id + ', article#' + this.id + ' div.title').css('cssText', "padding-bottom: 1px; margin-bottom: 4px; padding-left: 0px; padding-right: " + INDENT + "; margin-left: " + INDENT + "; background-color: " + bgcolor);
  625.  
  626. } else {
  627. if (msgs > -1) {
  628. root.appendChild(this);
  629. }
  630. }
  631. }
  632. // ---------------------------------------------------------------------
  633.  
  634.  
  635. jq('#commentForm').remove();
  636.  
  637. function makeTree() {
  638. msgs = -1;
  639. jq(".updatepage,._new_").remove();
  640.  
  641. jq("article.msg").each(doindent);
  642. idx = newid.shift(); // remove topic
  643.  
  644. addNavigateLinks(newid);
  645. newid.length = 0;
  646. // set message counter
  647. msgs = jq('div.comment article.msg').length;
  648. setCounter(thread_id, msgs);
  649. }
  650.  
  651. makeTree();
  652.  
  653. //var h1subj = jq('div.msg_body h1').get(0);
  654. //h1subj.innerHTML = '<br><u>' + h1subj.innerHTML + '</u><br><br>';
  655.  
  656. var urlhash = document.location.hash;
  657. if (urlhash) {
  658. urlhash = urlhash.split('#')[1];
  659. document.getElementById(urlhash).scrollIntoView();
  660. }
  661.  
  662. setTimeout(function() {
  663. window.onbeforeunload = null;
  664. }, 1000);
  665.  
  666. // ---------------------------------------------------------------------
RAW Paste Data