Facebook
From jebacz, 9 Years ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 1069
  1. // ==UserScript==
  2. // @name        karaunlocker
  3. // @namespace   karachan.org
  4. // @description A po szkole wchodziliśmy na kurahen :)
  5. // @version     1.3
  6. // @downloadURL https://gist.github.com/lanceq1337
  7.  
  8. // @grant       GM_addStyle
  9.  
  10. // @match       *://*.karachan.org/*
  11. // @exclude     http://www.karachan.org/*/src/*
  12. // @exclude     https://www.karachan.org/*/src/*
  13. // @exclude     http://karachan.org/*/src/*
  14. // @exclude     https://karachan.org/*/src/*
  15.  
  16. // @match       *://*.karachan.co/*
  17. // @exclude     http://www.karachan.co/*/src/*
  18. // @exclude     https://www.karachan.co/*/src/*
  19. // @exclude     http://karachan.co/*/src/*
  20. // @exclude     https://karachan.co/*/src/*
  21.  
  22. // @match       *://96.8.113.203/*
  23. // @exclude     http://96.8.113.203/*/src/*
  24. // @exclude     https://96.8.113.203/*/src/*
  25. // @exclude     http://96.8.113.203/*/src/*
  26. // @exclude     https://96.8.113.203/*/src/*
  27. // ==/UserScript==
  28.  
  29. /*jshint curly:true, noarg:true, indent:4, trailing:true, forin:true, noempty:true, quotmark:single, eqeqeq:true,
  30.  undef:true, bitwise:true, browser:true, devel:true, nonbsp:true */
  31.  
  32. /*global GM_addStyle:false */
  33.  
  34. document.cookie="usuń=to";
  35. localStorage.xD ="xD";
  36. document.cookie="zjedzmielone=1";
  37.  
  38. var FormValidator = (function () {
  39.         function FormValidator() {
  40.                 this.setSubmitAction();
  41.         }
  42.         FormValidator.prototype.setSubmitAction = function () {
  43.                 var _this = this;
  44.                 document.getElementById('submit').addEventListener('click', function (ev) {
  45.                         if (!_this.isFileInputFilled() && !_this.isPostTextFilled()) {
  46.                                 ev.preventDefault();
  47.                                 alert('Napisz post lub dodaj śmieszny obrazek');
  48.                                 return;
  49.                         }
  50.  
  51.                         if (document.cookie.indexOf('in_mod') === -1 && _this.getCaptchaFieldTextLenght() !== 6) {
  52.                                 ev.preventDefault();
  53.                                 alert('Ale kapcze to popraw');
  54.                                 return;
  55.                         }
  56.  
  57.                         if (_this.getFileSize() > _this.getMaxFileSize()) {
  58.                                 ev.preventDefault();
  59.                                 alert('Plik zbyt duży');
  60.                                 return;
  61.                         }
  62.  
  63.                         if (UrlChecker.isCurrentWebpageThread()) {
  64.                                 if (_this.isFileInputFilled() && !_this.isAllowedFileExt()) {
  65.                                         _this.reactToNotAllowedFileExt(ev);
  66.                                 }
  67.                                 return;
  68.                         }
  69.  
  70.                         if (!_this.isNoFileAllowed() && !_this.isFileInputFilled()) {
  71.                                 ev.preventDefault();
  72.                                 alert('Wybierz plik');
  73.                                 return;
  74.                         }
  75.  
  76.                         if (!_this.isFileInputFilled() && !_this.isNoFileChecked()) {
  77.                                 if (confirm('Wysłać bez pliku?')) {
  78.                                         _this.setNoFile();
  79.                                 } else {
  80.                                         ev.preventDefault();
  81.                                 }
  82.                                 return;
  83.                         }
  84.  
  85.                         if (_this.isFileInputFilled() && !_this.isAllowedFileExt()) {
  86.                                 _this.reactToNotAllowedFileExt(ev);
  87.                         }
  88.                 });
  89.         };
  90.  
  91.         FormValidator.prototype.reactToNotAllowedFileExt = function (ev) {
  92.                 if (!confirm('Plik najprawdopodobniej nie jest obsługiwany, pomimo to chcesz procedować dalej?')) {
  93.                         ev.preventDefault();
  94.                 }
  95.         };
  96.  
  97.         FormValidator.prototype.isPostTextFilled = function () {
  98.                 return this.getPostTextLength() > 0;
  99.         };
  100.  
  101.         FormValidator.prototype.getPostTextLength = function () {
  102.                 return document.getElementsByName('com')[0].value.length;
  103.         };
  104.  
  105.         FormValidator.prototype.isFileInputFilled = function () {
  106.                 var fileFile = document.getElementById('postFile');
  107.                 if (fileFile) {
  108.                         return fileFile.value !== '';
  109.                 } else {
  110.                         return false;
  111.                 }
  112.         };
  113.  
  114.         FormValidator.prototype.getFileSize = function () {
  115.                 if (!this.isFileInputFilled()) {
  116.                         return 0;
  117.                 }
  118.                 return document.getElementById('postFile').files[0].size;
  119.         };
  120.  
  121.         FormValidator.prototype.getMaxFileSize = function () {
  122.                 var maxFileList = document.getElementsByName('MAX_FILE_SIZE');
  123.                 if (maxFileList.length === 0) {
  124.                         return 0;
  125.                 }
  126.                 var valStr = maxFileList[0].value;
  127.                 return parseInt(valStr);
  128.         };
  129.  
  130.         FormValidator.prototype.getCaptchaFieldTextLenght = function () {
  131.                 var captchaField = document.getElementById('captchaField');
  132.                 if (captchaField) {
  133.                         return captchaField.value.length;
  134.                 } else {
  135.                         return 0;
  136.                 }
  137.         };
  138.  
  139.         FormValidator.prototype.isNoFileChecked = function () {
  140.                 if (this.isNoFileAllowed()) {
  141.                         return document.getElementById('nofile').checked;
  142.                 } else {
  143.                         return false;
  144.                 }
  145.         };
  146.  
  147.         FormValidator.prototype.isNoFileAllowed = function () {
  148.                 if (document.getElementById('nofile')) {
  149.                         return true;
  150.                 } else {
  151.                         return false;
  152.                 }
  153.         };
  154.  
  155.         FormValidator.prototype.isAllowedFileExt = function () {
  156.                 if (!this.isFileInputFilled()) {
  157.                         return false;
  158.                 }
  159.                 var fileName = document.getElementById('postFile').files[0].name;
  160.                 var ext = fileName.split('.').pop().toLowerCase();
  161.                 for (var i = 0; i < allowedFileExtensions.length; i++) {
  162.                         if (ext === allowedFileExtensions[i]) {
  163.                                 return true;
  164.                         }
  165.                 }
  166.                 return false;
  167.         };
  168.  
  169.         FormValidator.prototype.setNoFile = function () {
  170.                 document.getElementById('nofile').checked = true;
  171.         };
  172.         return FormValidator;
  173. })();
  174. var KurahenPremium = (function () {
  175.         function KurahenPremium() {
  176.                 this.formValidator = new FormValidator();
  177.                 var currentBoardName = UrlChecker.getCurrentBoardName();
  178.  
  179.                 if (currentBoardName === '' || UrlChecker.isCurrentPage404()) {
  180.                         return;
  181.                 } else if (currentBoardName === 'b') {
  182.                         this.changeBoardTitle(customBBoardTitle);
  183.                 }
  184.                 this.updatePageTitle();
  185.                 this.disableNightStyle();
  186.                 this.setCookie('regulamin', 'accepted');
  187.                 this.insertButtonBar();
  188.                 this.replaceEmailFieldWithSelect();
  189.                 this.showAllPostersEmails();
  190.  
  191.                 this.fixScrollingToTarget();
  192.                 this.fixAllExternalLinks();
  193.                 this.fixAllHiders();
  194.                 this.fixAllExpanders();
  195.  
  196.                 if (boardsWithId.indexOf(currentBoardName) > -1 && UrlChecker.isCurrentWebpageThread()) {
  197.                         this.colorizeAndNamePosters();
  198.                 }
  199.  
  200.                 if (enableBetterFonts) {
  201.                         this.changeFonts();
  202.                 }
  203.  
  204.                 if (deleteTextUnderPostForm) {
  205.                         this.removeTextUnderPostForm();
  206.                 }
  207.  
  208.                 if (biggerOnlineCountFont) {
  209.                         this.enlargeOnlineCountFont();
  210.                 }
  211.  
  212.                 /* variable used to change "highlight posts" button state */
  213.                 this.nowHighlightedPostsUserId = false;
  214.                 this.threadsWatcher = new ThreadsWatcher();
  215.         }
  216.         KurahenPremium.prototype.changeBoardTitle = function (newTitle) {
  217.                 document.title = newTitle;
  218.                 document.getElementsByClassName('boardTitle')[0].textContent = newTitle;
  219.         };
  220.  
  221.         KurahenPremium.prototype.updatePageTitle = function () {
  222.                 var page = parseInt(window.location.pathname.split('/')[2]);
  223.                 var prefix = '';
  224.  
  225.                 if (UrlChecker.isCurrentWebpageThread()) {
  226.                         prefix = this.getTopicFromFirstPostContent();
  227.                 } else if (!isNaN(page)) {
  228.                         prefix = 'Strona ' + page;
  229.                 }
  230.  
  231.                 if (prefix.length > 0) {
  232.                         prefix += ' - ';
  233.                 }
  234.  
  235.                 document.title = prefix + document.title;
  236.         };
  237.  
  238.         KurahenPremium.prototype.setCookie = function (name, value) {
  239.                 document.cookie = encodeURIComponent(name) + '=' + encodeURIComponent(value) + '; path=/; max-age=2592000';
  240.         };
  241.  
  242.         KurahenPremium.prototype.changeFonts = function () {
  243.                 var newLink = document.createElement('link');
  244.                 newLink.href = '//fonts.googleapis.com/css?family=Roboto:400,700&subset=latin,latin-ext';
  245.                 newLink.rel = 'stylesheet';
  246.                 var existingLink = document.getElementsByTagName('link')[0];
  247.                 existingLink.parentNode.insertBefore(newLink, existingLink);
  248.                 document.body.style.fontFamily = 'Roboto, "Helvetica Neue", Helvetica, Arial, sans-serif';
  249.         };
  250.  
  251.         KurahenPremium.prototype.getTopicFromFirstPostContent = function () {
  252.                 var postMessage = document.querySelector('.thread .postMessage').cloneNode(true);
  253.  
  254.                 var backlinks = postMessage.getElementsByClassName('backlink');
  255.                 if (backlinks.length > 0) {
  256.                         postMessage.removeChild(backlinks[0]);
  257.                 }
  258.  
  259.                 var links = postMessage.getElementsByClassName('postlink');
  260.                 for (var i = 0; i < links.length; i++) {
  261.                         links[i].parentNode.removeChild(links[i]);
  262.                 }
  263.  
  264.                 var quoteLinks = postMessage.getElementsByClassName('quotelink');
  265.                 for (var j = 0; j < quoteLinks.length; j++) {
  266.                         postMessage.removeChild(quoteLinks[i]);
  267.                 }
  268.  
  269.                 var postContent = postMessage.textContent.trim();
  270.                 if (postContent === '') {
  271.                         return '(brak treści posta)';
  272.                 }
  273.                 return postContent.substr(0, Math.min(postContent.length, 70));
  274.         };
  275.  
  276.         KurahenPremium.prototype.disableNightStyle = function () {
  277.                 var optionNight = document.querySelector('#stylechanger option[value$="night.css"]');
  278.                 optionNight.disabled = true;
  279.  
  280.                 var optionNight2 = document.querySelector('#stylechanger option[value$="night2.css"]');
  281.                 optionNight2.disabled = true;
  282.         };
  283.  
  284.         KurahenPremium.prototype.replaceEmailFieldWithSelect = function () {
  285.                 var emailField = document.querySelector('#postform input[name="email"]');
  286.  
  287.                 var select = document.createElement('select');
  288.                 select.name = 'email';
  289.                 select.style.margin = '0';
  290.                 select.style.width = '236px';
  291.                 select.addEventListener('change', function () {
  292.                         // noinspection JSPotentiallyInvalidUsageOfThis
  293.                         if (this.options[this.selectedIndex].value === 'custom') {
  294.                                 var textField = document.createElement('input');
  295.                                 textField.type = 'text';
  296.                                 textField.className = 'board-input';
  297.                                 textField.name = 'email';
  298.                                 select.parentNode.replaceChild(textField, select);
  299.                                 textField.focus();
  300.                         }
  301.                 }, false);
  302.  
  303.                 var optionBump = document.createElement('option');
  304.                 optionBump.value = '';
  305.                 optionBump.selected = true;
  306.                 optionBump.textContent = 'Podbij';
  307.                 select.appendChild(optionBump);
  308.  
  309.                 var optionSage = document.createElement('option');
  310.                 optionSage.value = 'sage';
  311.                 optionSage.textContent = 'Saguj';
  312.                 select.appendChild(optionSage);
  313.  
  314.                 var optionCustom = document.createElement('option');
  315.                 optionCustom.value = 'custom';
  316.                 optionCustom.textContent = 'Wpisz własny...';
  317.                 select.appendChild(optionCustom);
  318.  
  319.                 emailField.parentNode.replaceChild(select, emailField);
  320.         };
  321.  
  322.         KurahenPremium.prototype.showAllPostersEmails = function () {
  323.                 var postersEmails = document.getElementsByClassName('useremail');
  324.  
  325.                 for (var i = 0; i < postersEmails.length; i++) {
  326.                         postersEmails[i].textContent += ' (' + this.parseMailto(postersEmails[i].getAttribute('href')) + ') ';
  327.                         postersEmails[i].removeAttribute('href');
  328.                 }
  329.         };
  330.  
  331.         KurahenPremium.prototype.fixScrollingToTarget = function () {
  332.                 if (window.location.hash.length > 1) {
  333.                         setTimeout(function () {
  334.                                 document.querySelector(window.location.hash).scrollIntoView(true);
  335.                         }, 1000);
  336.                 }
  337.         };
  338.  
  339.         KurahenPremium.prototype.fixAllHiders = function () {
  340.                 var hiders = document.getElementsByClassName('hider');
  341.                 for (var i = 0; i < hiders.length; i++) {
  342.                         var hiderTextContent = hiders[i].textContent;
  343.                         if (hiderTextContent === '[-]') {
  344.                                 hiders[i].textContent = '[—]';
  345.                         } else if (hiderTextContent === '[+]') {
  346.                                 hiders[i].textContent = '[ + ]';
  347.                         }
  348.                 }
  349.         };
  350.  
  351.         KurahenPremium.prototype.fixAllExpanders = function () {
  352.                 var expanders = document.getElementsByClassName('expander');
  353.                 for (var i = 0; i < expanders.length; i++) {
  354.                         expanders[i].textContent = 'Rozwiń';
  355.                 }
  356.         };
  357.  
  358.         KurahenPremium.prototype.fixAllExternalLinks = function () {
  359.                 var links = document.getElementsByClassName('postlink');
  360.                 for (var i = 0; i < links.length; i++) {
  361.                         links[i].setAttribute('href', links[i].getAttribute('href').replace('https://href.li/?', ''));
  362.                         links[i].setAttribute('target', '_blank');
  363.                         links[i].setAttribute('rel', 'noreferrer');
  364.                 }
  365.  
  366.                 this.inlineVideoAndAudioLinks(links);
  367.         };
  368.  
  369.         /**
  370.          * @private
  371.          */
  372.         KurahenPremium.prototype.parseMailto = function (mailto) {
  373.                 return mailto.replace('mailto:', '');
  374.         };
  375.  
  376.         /**
  377.          * @private
  378.          */
  379.         KurahenPremium.prototype.inlineVideoAndAudioLinks = function (links) {
  380.                 for (var i = 0; i < links.length; i++) {
  381.                         var url = links[i].getAttribute('href');
  382.                         if (url.indexOf('http://vocaroo.com') > -1) {
  383.                                 var vocarooId = url.substr(url.length - 12, 12);
  384.  
  385.                                 var vocarooContainer = document.createElement('div');
  386.                                 vocarooContainer.innerHTML = '<object width="148" height="44"><param name="movie"' +
  387.                                         'value="http://vocaroo.com/player.swf?playMediaID=' + vocarooId + '&autoplay=0"/>' +
  388.                                         '<param name="wmode" value="transparent"/>' + '<embed src="http://vocaroo.com/player.swf?playMediaID=' +
  389.                                         vocarooId + '&autoplay=0" width="148" ' +
  390.                                         'height="44" wmode="transparent" type="application/x-shockwave-flash"></embed></object>';
  391.  
  392.                                 if (links[i].nextSibling) {
  393.                                         links[i].parentNode.insertBefore(vocarooContainer, links[i].nextSibling);
  394.                                 } else {
  395.                                         links[i].parentNode.appendChild(vocarooContainer);
  396.                                 }
  397.                                 links[i].style.display = 'none';
  398.                         }
  399.                 }
  400.         };
  401.  
  402.         KurahenPremium.prototype.colorizeAndNamePosters = function () {
  403.                 var postersIds = document.getElementsByClassName('posteruid');
  404.                 var postersStats = {};
  405.  
  406.                 var opId;
  407.                 for (var i = 0; i < postersIds.length; i++) {
  408.                         var posterId = this.parsePosterId(postersIds[i].textContent);
  409.                         postersIds[i].title = posterId;
  410.                         posterId = posterId.replace(/[\.|\/|\+|\-]/g, '_');
  411.  
  412.                         if (i === 0) {
  413.                                 opId = posterId;
  414.                         }
  415.  
  416.                         postersIds[i].className += ' poster-id-' + posterId;
  417.                         if (roundedIdBackground) {
  418.                                 postersIds[i].className += ' id-rounded';
  419.                         }
  420.                         if (posterId === opId) {
  421.                                 postersIds[i].textContent = '\u00a0OP nitki';
  422.                         } else {
  423.                                 postersIds[i].textContent = '\u00a0' + posterId;
  424.                         }
  425.  
  426.                         if (typeof postersStats[posterId] === 'undefined') {
  427.                                 postersStats[posterId] = [postersIds[i]];
  428.                         } else {
  429.                                 postersStats[posterId].push(postersIds[i]);
  430.                         }
  431.                 }
  432.  
  433.                 var style = '';
  434.                 for (var id in postersStats) {
  435.                         if (postersStats.hasOwnProperty(id) && postersStats[id].length > 1) {
  436.                                 style += '.poster-id-' + id + '{color:#000;background-color: ' + this.getNextColor() + ';}\n';
  437.                                 var numeral;
  438.                                 if (postersStats[id].length < 5) {
  439.                                         numeral = ' posty';
  440.                                 } else {
  441.                                         numeral = ' postów';
  442.                                 }
  443.  
  444.                                 if (showPostCountNearId) {
  445.                                         style += '.poster-id-' + id + ':after{content:" (';
  446.                                         style += postersStats[id].length + numeral + ')\u00a0"}\n';
  447.                                 }
  448.  
  449.                                 if (enableHighlightPostsButton) {
  450.                                         this.setHighlightPostsButton(postersStats[id], id);
  451.                                 }
  452.  
  453.                                 if (enableJumpButtons) {
  454.                                         this.setJumpButtons(postersStats[id]);
  455.                                 }
  456.                         }
  457.                 }
  458.  
  459.                 if (roundedIdBackground) {
  460.                         style += '.id-rounded { font-size: 11px; border-radius: 6px; padding: 0px 6px 0px 2px;}\n';
  461.                 }
  462.                 style += '.small-icon { font-size: 16px; vertical-align: middle }\n';
  463.                 style += '.post-animated { transition: opacity 0.4s}\n';
  464.                 style += '.hiden-post { opacity: ' + unhighlightedPostOpacity + '}\n';
  465.                 style += '.highlighting-button { font-size: 11px; cursor:pointer}\n';
  466.                 style += '.highlighting-button:hover { color: orange;}\n';
  467.                 GM_addStyle(style);
  468.  
  469.                 var allUserPosts = document.getElementsByClassName('postContainer');
  470.                 for (i = 0; i < allUserPosts.length; i++) {
  471.                         allUserPosts[i].classList.add('post-animated');
  472.                 }
  473.                 var firstPostBar = document.querySelector('.opContainer .postInfo');
  474.                 var threadPostersStats = document.createElement('span');
  475.                 threadPostersStats.textContent = ' (' + postersIds.length + ' postów od ' + Object.keys(postersStats).length +
  476.                         ' anonów)';
  477.                 firstPostBar.appendChild(threadPostersStats);
  478.         };
  479.  
  480.         /**
  481.          * @private
  482.          */
  483.         KurahenPremium.prototype.getNextColor = function () {
  484.                 if (colors.length > 0) {
  485.                         return colors.shift();
  486.                 } else {
  487.                         return '#' + Math.random().toString(16).substr(-6);
  488.                 }
  489.         };
  490.  
  491.         /**
  492.          * @private
  493.          */
  494.         KurahenPremium.prototype.parsePosterId = function (text) {
  495.                 return text.trim().substr(5, 8);
  496.         };
  497.  
  498.         /**
  499.          * @private
  500.          */
  501.         KurahenPremium.prototype.getPostNo = function (userPost) {
  502.                 var id = userPost.parentNode.parentNode.getAttribute('id');
  503.                 return id.substr(2, id.length - 2);
  504.         };
  505.  
  506.         KurahenPremium.prototype.setButtonLabelsForId = function (userId, buttonLabel, newTitle) {
  507.                 var buttons = document.querySelectorAll('[highlight-button-id="' + userId + '"]');
  508.                 for (var i = 0; i < buttons.length; i++) {
  509.                         buttons[i].textContent = buttonLabel;
  510.                         buttons[i].title = newTitle;
  511.                 }
  512.         };
  513.  
  514.         KurahenPremium.prototype.highlightPostsById = function (userId) {
  515.                 if (this.nowHighlightedPostsUserId) {
  516.                         var showPostsStr = ' Pokaż posty';
  517.  
  518.                         if (showPostCountNearHighlightPostsButton) {
  519.                                 showPostsStr += ' (' + document.getElementsByClassName('poster-id-' + userId).length + ')';
  520.                         }
  521.  
  522.                         this.setButtonLabelsForId(this.nowHighlightedPostsUserId, showPostsStr, 'Podświetl posty tego użytkownika');
  523.                 }
  524.  
  525.                 if (this.nowHighlightedPostsUserId === userId) {
  526.                         this.showAllPosts();
  527.                         this.nowHighlightedPostsUserId = false;
  528.                 } else {
  529.                         this.setButtonLabelsForId(userId, ' Pokaż wszystkie', 'Wróć do widoku wszystkich postów');
  530.                         this.hideAllPostsExcept(userId);
  531.                         this.nowHighlightedPostsUserId = userId;
  532.                 }
  533.         };
  534.  
  535.         KurahenPremium.prototype.hideAllPostsExcept = function (userId) {
  536.                 // lower opacity for all posts except these with given id
  537.                 var allPosts = document.getElementsByClassName('postContainer');
  538.                 for (var i = 0; i < allPosts.length; i++) {
  539.                         if (this.getIdFromPostContainer(allPosts[i]) === userId) {
  540.                                 allPosts[i].classList.remove('hiden-post');
  541.                                 continue;
  542.                         }
  543.                         allPosts[i].classList.add('hiden-post');
  544.                 }
  545.         };
  546.  
  547.         KurahenPremium.prototype.showAllPosts = function () {
  548.                 // set normal opacity for all posts
  549.                 var allPosts = document.getElementsByClassName('postContainer');
  550.                 for (var i = 0; i < allPosts.length; i++) {
  551.                         allPosts[i].classList.remove('hiden-post');
  552.                 }
  553.         };
  554.  
  555.         KurahenPremium.prototype.getIdFromPostContainer = function (postContainer) {
  556.                 // depends on modified page src
  557.                 var idElement = postContainer.getElementsByClassName('posteruid')[0];
  558.                 for (var i = 0; idElement.classList.length; i++) {
  559.                         if (idElement.classList.item(i).indexOf('poster-id-') > -1) {
  560.                                 return idElement.classList.item(i).substr('poster-id-'.length, 8);
  561.                         }
  562.                 }
  563.                 return null;
  564.         };
  565.  
  566.         KurahenPremium.prototype.setHighlightPostsButton = function (userPosts, userId) {
  567.                 var self = this;
  568.                 var highlightPostsCallback = function () {
  569.                         self.highlightPostsById(userId);
  570.                 };
  571.                 for (var i = 0; i < userPosts.length; i++) {
  572.                         var showPostsButton = document.createElement('span');
  573.                         var showPostsStr = ' Pokaż posty';
  574.  
  575.                         if (showPostCountNearHighlightPostsButton) {
  576.                                 showPostsStr += ' (' + userPosts.length + ')';
  577.                         }
  578.  
  579.                         showPostsButton.textContent = showPostsStr;
  580.                         showPostsButton.title = 'Podświetl posty tego użytkownika';
  581.                         showPostsButton.className = 'highlighting-button';
  582.                         showPostsButton.setAttribute('highlight-button-id', userId);
  583.                         showPostsButton.addEventListener('click', highlightPostsCallback, false);
  584.  
  585.                         userPosts[i].parentNode.appendChild(showPostsButton);
  586.                 }
  587.         };
  588.  
  589.         KurahenPremium.prototype.setJumpButtonForPost = function (post, prev, next) {
  590.                 var newButtonsContainer = document.createElement('span');
  591.                 newButtonsContainer.style.marginLeft = '3px';
  592.  
  593.                 if (prev !== null) {
  594.                         var upButton = document.createElement('a');
  595.                         upButton.className = 'fa fa-chevron-up small-icon';
  596.                         upButton.title = 'Poprzedni post tego użytkownika';
  597.                         upButton.href = '#p' + prev;
  598.                         newButtonsContainer.appendChild(upButton);
  599.                 }
  600.                 if (next !== null) {
  601.                         var downButton = document.createElement('a');
  602.                         downButton.className = 'fa fa-chevron-down small-icon';
  603.                         downButton.title = 'Następny post tego użytkownika';
  604.                         downButton.href = '#p' + next;
  605.                         newButtonsContainer.appendChild(downButton);
  606.                 }
  607.  
  608.                 post.parentNode.appendChild(newButtonsContainer);
  609.         };
  610.  
  611.         KurahenPremium.prototype.setJumpButtons = function (userPosts) {
  612.                 var postsNo = [];
  613.  
  614.                 for (var i = 0; i < userPosts.length; i++) {
  615.                         postsNo.push(this.getPostNo(userPosts[i]));
  616.                 }
  617.  
  618.                 this.setJumpButtonForPost(userPosts[0], null, postsNo[1]);
  619.                 this.setJumpButtonForPost(userPosts[userPosts.length - 1], postsNo[postsNo.length - 2], null);
  620.  
  621.                 for (i = 1; i < userPosts.length - 1; i++) {
  622.                         this.setJumpButtonForPost(userPosts[i], postsNo[i - 1], postsNo[i + 1]);
  623.                 }
  624.         };
  625.  
  626.         KurahenPremium.prototype.insertButtonBar = function () {
  627.                 var postForm = document.getElementById('postform');
  628.                 var textarea = document.querySelector('#postform textarea');
  629.                 var buttonBar = document.createElement('div');
  630.                 buttonBar.style.textAlign = 'center';
  631.  
  632.                 this.insertTextFormattingButtons(textarea, buttonBar);
  633.                 this.insertSpecialCharButtons(textarea, buttonBar);
  634.                 this.insertWordfilterList(textarea, buttonBar);
  635.  
  636.                 postForm.insertBefore(buttonBar, postForm.firstChild);
  637.         };
  638.  
  639.         /**
  640.          * @private
  641.          */
  642.         KurahenPremium.prototype.insertTextFormattingButtons = function (textarea, buttonBar) {
  643.                 var onButtonClick = function () {
  644.                         var startTag = '[' + this.value + ']';
  645.                         var endTag = '[/' + this.value + ']';
  646.  
  647.                         var textBeforeSelection = textarea.value.substring(0, textarea.selectionStart);
  648.                         var selectedText = textarea.value.substring(textarea.selectionStart, textarea.selectionEnd);
  649.                         var textAfterSelection = textarea.value.substring(textarea.selectionEnd, textarea.value.length);
  650.  
  651.                         textarea.value = textBeforeSelection + startTag + selectedText + endTag + textAfterSelection;
  652.  
  653.                         textarea.focus();
  654.                         textarea.selectionStart += startTag.length;
  655.                         textarea.selectionEnd = textarea.selectionStart + selectedText.length;
  656.                 };
  657.  
  658.                 for (var i = 0; i < bbCodes.length; i++) {
  659.                         var button = document.createElement('input');
  660.                         button.type = 'button';
  661.                         button.value = bbCodes[i];
  662.                         button.style.padding = '0 7px';
  663.                         button.addEventListener('click', onButtonClick, false);
  664.                         buttonBar.appendChild(button);
  665.                 }
  666.         };
  667.  
  668.         /**
  669.          * @private
  670.          */
  671.         KurahenPremium.prototype.insertWordfilterList = function (textarea, buttonBar) {
  672.                 var wordfiltersSelect = document.createElement('select');
  673.  
  674.                 var defaultOption = document.createElement('option');
  675.                 defaultOption.value = '';
  676.                 defaultOption.disabled = true;
  677.                 defaultOption.selected = true;
  678.                 defaultOption.textContent = 'WORDFILTRY';
  679.                 wordfiltersSelect.appendChild(defaultOption);
  680.  
  681.                 wordfiltersSelect.addEventListener('change', function () {
  682.                         // noinspection JSPotentiallyInvalidUsageOfThis
  683.                         var textToInsert = this.options[this.selectedIndex].value;
  684.                         var textBeforeEndOfSelection = textarea.value.substring(0, textarea.selectionEnd);
  685.                         var textAfterEndOfSelection = textarea.value.substring(textarea.selectionEnd, textarea.value.length);
  686.  
  687.                         textarea.value = textBeforeEndOfSelection + textToInsert + textAfterEndOfSelection;
  688.  
  689.                         textarea.focus();
  690.                         textarea.selectionStart = textBeforeEndOfSelection.length + textToInsert.length;
  691.                         textarea.selectionEnd = textarea.selectionStart;
  692.  
  693.                         // noinspection JSPotentiallyInvalidUsageOfThis
  694.                         this.selectedIndex = 0;
  695.                 }, false);
  696.  
  697.                 for (var j = 0; j < wordfilters.length; j++) {
  698.                         var option = document.createElement('option');
  699.                         option.value = wordfilters[j][0];
  700.                         option.textContent = wordfilters[j][1];
  701.                         wordfiltersSelect.appendChild(option);
  702.                 }
  703.  
  704.                 buttonBar.appendChild(wordfiltersSelect);
  705.         };
  706.  
  707.         /**
  708.          * @private
  709.          */
  710.         KurahenPremium.prototype.insertSpecialCharButtons = function (textarea, buttonBar) {
  711.                 var onButtonClick = function () {
  712.                         var injectedChar;
  713.                         for (var i = 0; i < specialCharacters.length; i++) {
  714.                                 if (specialCharacters[i].buttonLabel === this.value) {
  715.                                         injectedChar = specialCharacters[i].contentToInsert;
  716.                                         break;
  717.                                 }
  718.                         }
  719.  
  720.                         var beforeSelect = textarea.value.substring(0, textarea.selectionStart);
  721.                         var afterSelect = textarea.value.substring(textarea.selectionStart, textarea.value.length);
  722.                         textarea.value = beforeSelect + injectedChar + afterSelect;
  723.  
  724.                         textarea.focus();
  725.                         textarea.selectionStart += 1;
  726.                         textarea.selectionEnd = textarea.selectionStart;
  727.                 };
  728.  
  729.                 for (var i = 0; i < specialCharacters.length; i++) {
  730.                         var button = document.createElement('input');
  731.                         button.type = 'button';
  732.                         button.value = specialCharacters[i].buttonLabel;
  733.                         button.title = specialCharacters[i].buttonTitle;
  734.                         button.style.padding = '0 7px';
  735.                         button.addEventListener('click', onButtonClick, false);
  736.                         buttonBar.appendChild(button);
  737.                 }
  738.         };
  739.  
  740.         /**
  741.          * @private
  742.          */
  743.         KurahenPremium.prototype.removeTextUnderPostForm = function () {
  744.                 var rules = document.querySelector('tr.rules');
  745.                 if (rules !== null) {
  746.                         rules.parentNode.removeChild(rules);
  747.                 }
  748.         };
  749.  
  750.         /**
  751.          * @private
  752.          */
  753.         KurahenPremium.prototype.enlargeOnlineCountFont = function () {
  754.                 var counter = document.getElementById('counter');
  755.                 var online = counter.lastChild.textContent;
  756.                 counter.removeChild(counter.lastChild);
  757.                 var newElement = document.createElement('b');
  758.                 newElement.textContent = online;
  759.                 counter.appendChild(newElement);
  760.  
  761.                 var container = counter.parentElement;
  762.                 container.style.fontSize = '20px';
  763.         };
  764.         return KurahenPremium;
  765. })();
  766. var UrlChecker;
  767. (function (UrlChecker) {
  768.         'use strict';
  769.  
  770.         function isCurrentWebpageThread() {
  771.                 return window.location.pathname.split('/')[2] === 'res';
  772.         }
  773.         UrlChecker.isCurrentWebpageThread = isCurrentWebpageThread;
  774.  
  775.         function isCurrentPage404() {
  776.                 return document.title === '404 Not Found';
  777.         }
  778.         UrlChecker.isCurrentPage404 = isCurrentPage404;
  779.  
  780.         function getCurrentBoardName() {
  781.                 var shouldBeBoard = window.location.pathname.split('/')[1];
  782.                 if (shouldBeBoard === 'menu.html') {
  783.                         return '';
  784.                 }
  785.                 if (shouldBeBoard === 'news.html') {
  786.                         return '';
  787.                 }
  788.                 return shouldBeBoard;
  789.         }
  790.         UrlChecker.getCurrentBoardName = getCurrentBoardName;
  791. })(UrlChecker || (UrlChecker = {}));
  792. var ThreadsWatcher = (function () {
  793.         function ThreadsWatcher() {
  794.                 this.loadWatchedThreads();
  795.                 this.insertThreadsListWindow();
  796.                 this.addWatchButtonsToPosts();
  797.         }
  798.         ThreadsWatcher.prototype.loadWatchedThreads = function () {
  799.                 var item = localStorage.getItem('KurahenPremium_WatchedThreads');
  800.                 if (item === null || item === 'null') {
  801.                         this.watchedThreads = {};
  802.                 } else {
  803.                         this.watchedThreads = JSON.parse(item);
  804.                 }
  805.         };
  806.  
  807.         ThreadsWatcher.prototype.saveWatchedThreads = function () {
  808.                 // Protection from concurrent modification
  809.                 var savedWatchedThreads = JSON.parse(localStorage.getItem('KurahenPremium_WatchedThreads')) || {};
  810.                 this.mergeWatchedThreads(savedWatchedThreads, this.watchedThreads);
  811.  
  812.                 localStorage.setItem('KurahenPremium_WatchedThreads', JSON.stringify(savedWatchedThreads));
  813.         };
  814.  
  815.         ThreadsWatcher.prototype.getWatchedThreadsWindowTopPosition = function () {
  816.                 var item = localStorage.getItem('KurahenPremium_WatchedThreads_Top');
  817.                 if (item === null || item === '') {
  818.                         return '35px';
  819.                 } else {
  820.                         return item;
  821.                 }
  822.         };
  823.  
  824.         ThreadsWatcher.prototype.setWatchedThreadsWindowTopPosition = function (position) {
  825.                 localStorage.setItem('KurahenPremium_WatchedThreads_Top', position);
  826.         };
  827.  
  828.         ThreadsWatcher.prototype.getWatchedThreadsWindowLeftPosition = function () {
  829.                 var item = localStorage.getItem('KurahenPremium_WatchedThreads_Left');
  830.                 if (item === null || item === '') {
  831.                         return '4px';
  832.                 } else {
  833.                         return item;
  834.                 }
  835.         };
  836.  
  837.         ThreadsWatcher.prototype.setWatchedThreadsWindowLeftPosition = function (position) {
  838.                 localStorage.setItem('KurahenPremium_WatchedThreads_Left', position);
  839.         };
  840.  
  841.         ThreadsWatcher.prototype.getWatchedThreadsWindowCssPosition = function () {
  842.                 var item = localStorage.getItem('KurahenPremium_WatchedThreads_CSS_Position');
  843.                 if (item === null || item === '') {
  844.                         return 'absolute';
  845.                 } else {
  846.                         return item;
  847.                 }
  848.         };
  849.  
  850.         ThreadsWatcher.prototype.setWatchedThreadsWindowCssPosition = function (positionProperity) {
  851.                 localStorage.setItem('KurahenPremium_WatchedThreads_CSS_Position', positionProperity);
  852.         };
  853.  
  854.         /**
  855.          * @private
  856.          */
  857.         ThreadsWatcher.prototype.mergeWatchedThreads = function (originalObject, objectToAppend) {
  858.                 for (var item in objectToAppend) {
  859.                         if (objectToAppend.hasOwnProperty(item)) {
  860.                                 // Add not removed threads
  861.                                 if (objectToAppend[item] !== null) {
  862.                                         originalObject[item] = objectToAppend[item];
  863.                                 } else if (originalObject[item] !== null) {
  864.                                         delete originalObject[item];
  865.                                 }
  866.                         }
  867.                 }
  868.         };
  869.  
  870.         ThreadsWatcher.prototype.getThreadObject = function (postId, boardName) {
  871.                 return this.watchedThreads['th_' + boardName + '_' + postId];
  872.         };
  873.  
  874.         ThreadsWatcher.prototype.addThreadObject = function (postId, boardName, lastReadPostId, topic) {
  875.                 this.watchedThreads['th_' + boardName + '_' + postId] = {
  876.                         'id': postId,
  877.                         'boardName': boardName,
  878.                         'lastReadPostId': lastReadPostId,
  879.                         'topic': topic
  880.                 };
  881.         };
  882.  
  883.         ThreadsWatcher.prototype.updateThreadObject = function (postId, boardName, lastReadPostId) {
  884.                 this.watchedThreads['th_' + boardName + '_' + postId].lastReadPostId = lastReadPostId;
  885.         };
  886.  
  887.         ThreadsWatcher.prototype.removeThreadObject = function (postId, boardName) {
  888.                 this.watchedThreads['th_' + boardName + '_' + postId] = null;
  889.         };
  890.  
  891.         ThreadsWatcher.prototype.threadObjectExists = function (postId, boardName) {
  892.                 return typeof this.watchedThreads['th_' + boardName + '_' + postId] === 'object' && this.watchedThreads['th_' +
  893.                         boardName + '_' + postId] !== null;
  894.         };
  895.  
  896.         ThreadsWatcher.prototype.threadsSize = function () {
  897.                 return Object.keys(this.watchedThreads).length;
  898.         };
  899.  
  900.         ThreadsWatcher.prototype.getWatchedThreadsList = function () {
  901.                 return this.watchedThreads;
  902.         };
  903.  
  904.         ThreadsWatcher.prototype.insertThreadsListWindow = function () {
  905.                 var _this = this;
  906.                 this.threadsListWindow = document.createElement('div');
  907.                 this.threadsListWindow.id = 'watcher_box';
  908.                 this.threadsListWindow.className = 'movable';
  909.                 this.threadsListWindow.style.height = 'auto';
  910.                 this.threadsListWindow.style.minHeight = '100px';
  911.                 this.threadsListWindow.style.width = 'auto';
  912.                 this.threadsListWindow.style.minWidth = '250px';
  913.                 this.threadsListWindow.style.position = this.getWatchedThreadsWindowCssPosition();
  914.                 this.threadsListWindow.style.top = this.getWatchedThreadsWindowTopPosition();
  915.                 this.threadsListWindow.style.left = this.getWatchedThreadsWindowLeftPosition();
  916.                 this.threadsListWindow.style.padding = '5px';
  917.  
  918.                 var threadsListWindowTitle = document.createElement('small');
  919.                 threadsListWindowTitle.textContent = 'Obserwowane nitki';
  920.                 this.threadsListWindow.appendChild(threadsListWindowTitle);
  921.  
  922.                 var threadsListWindowSticker = document.createElement('img');
  923.                 threadsListWindowSticker.src = '/img/sticky.gif';
  924.                 threadsListWindowSticker.style.position = 'absolute';
  925.                 if (this.threadsListWindow.style.position === 'absolute') {
  926.                         threadsListWindowSticker.style.opacity = '0.25';
  927.                 } else {
  928.                         threadsListWindowSticker.style.opacity = '1.0';
  929.                 }
  930.                 threadsListWindowSticker.style.right = '0px';
  931.                 threadsListWindowSticker.style.cursor = 'default';
  932.                 threadsListWindowSticker.onclick = function (ev) {
  933.                         var stick = ev.toElement;
  934.                         if (stick.style.opacity === '1') {
  935.                                 stick.style.opacity = '0.25';
  936.                                 _this.threadsListWindow.style.position = 'absolute';
  937.                                 _this.setWatchedThreadsWindowCssPosition('absolute');
  938.                                 var newtop = parseInt(_this.threadsListWindow.style.top) + document.body.scrollTop;
  939.                                 _this.threadsListWindow.style.top = newtop + 'px';
  940.                         } else {
  941.                                 stick.style.opacity = '1';
  942.                                 _this.threadsListWindow.style.position = 'fixed';
  943.                                 _this.setWatchedThreadsWindowCssPosition('fixed');
  944.                                 newtop = parseInt(_this.threadsListWindow.style.top) - document.body.scrollTop;
  945.                                 _this.threadsListWindow.style.top = newtop + 'px';
  946.                         }
  947.                 };
  948.                 this.threadsListWindow.appendChild(threadsListWindowSticker);
  949.  
  950.                 this.threadsHtmlList = document.createElement('ul');
  951.                 this.threadsHtmlList.id = 'watched_list';
  952.                 this.threadsListWindow.appendChild(this.threadsHtmlList);
  953.  
  954.                 var threads = this.getWatchedThreadsList();
  955.                 for (var item in threads) {
  956.                         if (threads.hasOwnProperty(item) && threads[item] !== null) {
  957.                                 this.addThreadListWindowEntry(threads[item].id, threads[item].boardName, threads[item].lastReadPostId, -1,
  958.                                         threads[item].topic);
  959.                         }
  960.                 }
  961.  
  962.                 var self = this;
  963.                 this.threadsListWindow.addEventListener('mouseout', function () {
  964.                         self.setWatchedThreadsWindowTopPosition(self.threadsListWindow.style.top);
  965.                         self.setWatchedThreadsWindowLeftPosition(self.threadsListWindow.style.left);
  966.                 }, false);
  967.  
  968.                 document.body.appendChild(this.threadsListWindow);
  969.  
  970.                 var script = document.createElement('script');
  971.                 script.textContent = '$("#watcher_box").drags();';
  972.                 document.body.appendChild(script);
  973.         };
  974.  
  975.         ThreadsWatcher.prototype.addThreadListWindowEntry = function (id, boardName, lastReadPostId, unreadPostsNumber,
  976.                 topic) {
  977.                 var entry = document.createElement('li');
  978.                 entry.id = 'wl_' + boardName + '_' + id;
  979.  
  980.                 var link = document.createElement('a');
  981.                 link.href = '/' + boardName + '/res/' + id + '.html#p' + lastReadPostId;
  982.                 entry.appendChild(link);
  983.  
  984.                 var unreadPostsSpan = document.createElement('span');
  985.                 unreadPostsSpan.className = 'unreadPostsNumber';
  986.                 unreadPostsSpan.textContent = '[' + (unreadPostsNumber >= 0 ? unreadPostsNumber : 'Ładowanie...') + '] ';
  987.                 link.appendChild(unreadPostsSpan);
  988.  
  989.                 var linkTextSpan = document.createElement('span');
  990.                 linkTextSpan.textContent = '/' + boardName + '/' + id + ': ' + topic;
  991.                 link.appendChild(linkTextSpan);
  992.  
  993.                 this.threadsHtmlList.appendChild(entry);
  994.  
  995.                 var self = this;
  996.                 if (this.getCurrentBoardName() === boardName && id === this.getCurrentThreadId()) {
  997.                         lastReadPostId = this.getNewestPostIdFromThread(id);
  998.                         unreadPostsSpan.textContent = '[0] ';
  999.                         self.updateThreadObject(id, boardName, lastReadPostId);
  1000.                         this.saveWatchedThreads();
  1001.                 } else if (unreadPostsNumber < 0) {
  1002.                         this.getNumberOfNewPosts(boardName, id, lastReadPostId, function (boardName, threadId, lastReadPostId,
  1003.                                 numberOfNewPosts, forceUpdate, status) {
  1004.                                 if (status === 200 && (numberOfNewPosts > 0 || !hideThreadsWithNoNewPosts)) {
  1005.                                         self.updateThreadListWindowEntry(threadId, boardName, lastReadPostId, numberOfNewPosts);
  1006.                                 } else if (status === 200 && hideThreadsWithNoNewPosts && numberOfNewPosts === 0) {
  1007.                                         self.removeThreadListWindowEntry(threadId, boardName);
  1008.                                 } else if (status === 404) {
  1009.                                         self.removeThreadListWindowEntry(threadId, boardName);
  1010.                                         self.removeThreadObject(threadId, boardName);
  1011.                                         self.saveWatchedThreads();
  1012.                                 } else {
  1013.                                         unreadPostsSpan.textContent = '[?] ';
  1014.                                 }
  1015.  
  1016.                                 if (forceUpdate) {
  1017.                                         self.updateThreadObject(threadId, boardName, lastReadPostId);
  1018.                                         self.saveWatchedThreads();
  1019.                                 }
  1020.                         });
  1021.                 }
  1022.         };
  1023.  
  1024.         ThreadsWatcher.prototype.updateThreadListWindowEntry = function (id, boardName, lastReadPostId, unreadPostsNumber) {
  1025.                 var entry = document.getElementById('wl_' + boardName + '_' + id);
  1026.                 if (entry === null) {
  1027.                         console.error('Cannot update nonexistent thread /' + boardName + '/' + id);
  1028.                         return;
  1029.                 }
  1030.  
  1031.                 var link = entry.querySelector('a');
  1032.                 link.href = '/' + boardName + '/res/' + id + '.html#p' + lastReadPostId;
  1033.  
  1034.                 var unreadPostsSpan = link.querySelector('.unreadPostsNumber');
  1035.                 unreadPostsSpan.textContent = '[' + (unreadPostsNumber >= 0 ? unreadPostsNumber : 'Ładowanie...') + '] ';
  1036.         };
  1037.  
  1038.         ThreadsWatcher.prototype.removeThreadListWindowEntry = function (id, boardName) {
  1039.                 var entry = document.getElementById('wl_' + boardName + '_' + id);
  1040.  
  1041.                 if (entry === null) {
  1042.                         return;
  1043.                 }
  1044.                 this.threadsHtmlList.removeChild(entry);
  1045.         };
  1046.  
  1047.         ThreadsWatcher.prototype.addWatchButtonsToPosts = function () {
  1048.                 var postsBars = document.querySelectorAll('.opContainer .postInfo');
  1049.                 var self = this;
  1050.                 var toggleWatchLabel = function () {
  1051.                         if (this.textContent === 'Nie obserwuj') {
  1052.                                 this.textContent = 'Obserwuj';
  1053.                         } else {
  1054.                                 this.textContent = 'Nie obserwuj';
  1055.                         }
  1056.                         self.addRemoveWatchedThread(parseInt(this.getAttribute('data-post-id')), self.getCurrentBoardName());
  1057.                 };
  1058.  
  1059.                 for (var i = 0; i < postsBars.length; i++) {
  1060.                         var postId = this.parsePostId(postsBars[i]);
  1061.                         var watchButton = document.createElement('a');
  1062.                         watchButton.style.cursor = 'pointer';
  1063.                         watchButton.setAttribute('data-post-id', postId.toString());
  1064.                         watchButton.addEventListener('click', toggleWatchLabel, false);
  1065.  
  1066.                         var watchButtonContainer = document.createElement('span');
  1067.                         watchButtonContainer.className = 'watch-button-container';
  1068.                         watchButtonContainer.appendChild(watchButton);
  1069.  
  1070.                         var currentBoardName = this.getCurrentBoardName();
  1071.                         if (this.threadObjectExists(postId, currentBoardName)) {
  1072.                                 watchButton.textContent = 'Nie obserwuj';
  1073.                         } else {
  1074.                                 watchButton.textContent = 'Obserwuj';
  1075.                         }
  1076.  
  1077.                         var postNum = postsBars[i].querySelector('span.postNum');
  1078.                         postNum.insertBefore(watchButtonContainer, postNum.querySelector('span'));
  1079.                 }
  1080.  
  1081.                 GM_addStyle('.watch-button-container:before {content: " [";}\n' + '.watch-button-container:after{content: "] ";}');
  1082.         };
  1083.  
  1084.         ThreadsWatcher.prototype.addRemoveWatchedThread = function (postId, boardName) {
  1085.                 // Add new thread to watchlist
  1086.                 if (!this.threadObjectExists(postId, boardName)) {
  1087.                         var newestPostId = this.getNewestPostIdFromThread(postId);
  1088.                         var topic = this.getTopicOfThread(postId);
  1089.                         this.addThreadObject(postId, boardName, newestPostId, topic);
  1090.                         this.addThreadListWindowEntry(postId, boardName, newestPostId, 0, topic);
  1091.                 } else {
  1092.                         this.removeThreadListWindowEntry(postId, boardName);
  1093.                         this.removeThreadObject(postId, boardName);
  1094.                 }
  1095.  
  1096.                 this.saveWatchedThreads();
  1097.         };
  1098.  
  1099.         ThreadsWatcher.prototype.getNewestPostIdFromThread = function (threadId) {
  1100.                 var posts = document.querySelectorAll('.thread[id$="' + threadId + '"] .postContainer');
  1101.                 return parseInt(posts[posts.length - 1].id.substr(2));
  1102.         };
  1103.  
  1104.         ThreadsWatcher.prototype.getNumberOfNewPosts = function (boardName, threadId, lastPostId, callback) {
  1105.                 var request = new XMLHttpRequest();
  1106.                 request.open('GET', '/' + boardName + '/res/' + threadId + '.html', true);
  1107.  
  1108.                 var self = this;
  1109.                 request.onload = function () {
  1110.                         var forceUpdate = false;
  1111.  
  1112.                         // On error
  1113.                         if (request.status !== 200) {
  1114.                                 callback(boardName, threadId, lastPostId, -1, forceUpdate, request.status);
  1115.                                 return;
  1116.                         }
  1117.  
  1118.                         // On success
  1119.                         var parser = new DOMParser();
  1120.                         var doc = parser.parseFromString(request.responseText, 'text/html');
  1121.  
  1122.                         var postsContainers = doc.getElementsByClassName('postContainer');
  1123.                         var numberOfNewPosts = 0;
  1124.                         for (var i = 0; i < postsContainers.length; i++) {
  1125.                                 if (self.parsePostId(postsContainers[i]) === lastPostId) {
  1126.                                         numberOfNewPosts = postsContainers.length - 1 - i;
  1127.                                         break;
  1128.                                 }
  1129.                         }
  1130.  
  1131.                         // When last read post was deleted
  1132.                         if (numberOfNewPosts === 0) {
  1133.                                 var lastDetectedPostId = self.parsePostId(postsContainers[postsContainers.length - 1]);
  1134.                                 if (lastDetectedPostId !== lastPostId) {
  1135.                                         lastPostId = lastDetectedPostId;
  1136.                                         forceUpdate = true;
  1137.                                 }
  1138.                         }
  1139.  
  1140.                         callback(boardName, threadId, lastPostId, numberOfNewPosts, forceUpdate, 200);
  1141.                 };
  1142.                 request.send();
  1143.         };
  1144.  
  1145.         ThreadsWatcher.prototype.getNumberOfNewPostsJSON = function (boardName, threadId, lastPostId, callback) {
  1146.                 var request = new XMLHttpRequest();
  1147.  
  1148.                 request.open('GET', '/' + boardName + '/res/' + threadId + '.json');
  1149.                 request.onload = function () {
  1150.                         var forceUpdate = false;
  1151.  
  1152.                         // On error
  1153.                         if (request.status !== 200) {
  1154.                                 callback(boardName, threadId, lastPostId, -1, forceUpdate, request.status);
  1155.                                 return;
  1156.                         }
  1157.  
  1158.                         // On success
  1159.                         var posts = JSON.parse(request.responseText).posts;
  1160.                         posts.shift();
  1161.  
  1162.                         // If only op post
  1163.                         if (posts.length === 0) {
  1164.                                 callback(boardName, threadId, lastPostId, 0, forceUpdate, request.status);
  1165.                         }
  1166.  
  1167.                         posts.sort(function (a, b) {
  1168.                                 return parseInt(a.no) - parseInt(b.no);
  1169.                         });
  1170.  
  1171.                         var numberOfNewPosts = 0;
  1172.                         for (var i = 0; i < posts.length; i++) {
  1173.                                 if (parseInt(posts[i].no) === lastPostId) {
  1174.                                         numberOfNewPosts = posts.length - 1 - i;
  1175.                                         break;
  1176.                                 }
  1177.                         }
  1178.  
  1179.                         // When last read post was deleted
  1180.                         if (numberOfNewPosts === 0) {
  1181.                                 var lastDetectedPostId = parseInt(posts[posts.length - 1].no);
  1182.                                 if (lastDetectedPostId !== lastPostId) {
  1183.                                         lastPostId = lastDetectedPostId;
  1184.                                         forceUpdate = true;
  1185.                                 }
  1186.                         }
  1187.                         callback(boardName, threadId, lastPostId, numberOfNewPosts, forceUpdate, request.status);
  1188.                 };
  1189.                 request.send();
  1190.         };
  1191.  
  1192.         /**
  1193.          * @private
  1194.          */
  1195.         ThreadsWatcher.prototype.parsePostId = function (htmlElement) {
  1196.                 return parseInt(htmlElement.id.substr(2));
  1197.         };
  1198.  
  1199.         /**
  1200.          * @private
  1201.          */
  1202.         ThreadsWatcher.prototype.getCurrentBoardName = function () {
  1203.                 return document.querySelector('meta[property="og:boardname"]').getAttribute('content');
  1204.         };
  1205.  
  1206.         /**
  1207.          * @private
  1208.          */
  1209.         ThreadsWatcher.prototype.getCurrentThreadId = function () {
  1210.                 if (window.location.pathname.split('/')[2] !== 'res') {
  1211.                         return -1;
  1212.                 }
  1213.                 return parseInt(document.querySelector('.thread .opContainer').id.substr(2));
  1214.         };
  1215.  
  1216.         ThreadsWatcher.prototype.getTopicOfThread = function (threadId) {
  1217.                 var postMessage = document.querySelector('.thread[id$="' + threadId + '"] .postMessage').cloneNode(true);
  1218.  
  1219.                 var backlinks = postMessage.getElementsByClassName('backlink');
  1220.                 if (backlinks.length > 0) {
  1221.                         postMessage.removeChild(backlinks[0]);
  1222.                 }
  1223.  
  1224.                 var links = postMessage.getElementsByClassName('postlink');
  1225.                 for (var i = 0; i < links.length; i++) {
  1226.                         links[i].parentNode.removeChild(links[i]);
  1227.                 }
  1228.  
  1229.                 var quoteLinks = postMessage.getElementsByClassName('quotelink');
  1230.                 for (var j = 0; j < quoteLinks.length; j++) {
  1231.                         postMessage.removeChild(quoteLinks[i]);
  1232.                 }
  1233.  
  1234.                 var postContent = postMessage.textContent.trim();
  1235.                 if (postContent === '') {
  1236.                         return '(brak treści posta)';
  1237.                 }
  1238.                 return postContent.substr(0, Math.min(postContent.length, 25));
  1239.         };
  1240.         return ThreadsWatcher;
  1241. })();
  1242. // Konfiguracja
  1243. var customBBoardTitle = '/b/ - Random';
  1244. var enableBetterFonts = true;
  1245. var deleteTextUnderPostForm = false;
  1246. var biggerOnlineCountFont = false;
  1247. var hideThreadsWithNoNewPosts = false;
  1248. var enableHighlightPostsButton = true;
  1249.  
  1250. // postów danego użytkownika
  1251. var enableJumpButtons = true;
  1252.  
  1253. // Zaawansowana konfiguracja
  1254. var unhighlightedPostOpacity = 0.3;
  1255.  
  1256. // użytkownika; 0 - niewidoczny, 1 - nieprzezroczysty
  1257. var bbCodes = ['b', 'i', 'u', 'code', 'spoiler'];
  1258. var specialCharacters = [{
  1259.         contentToInsert: '\u2026',
  1260.         buttonTitle: 'Wielokropek',
  1261.         buttonLabel: '\u2026'
  1262. }, {
  1263.         contentToInsert: '\u200b',
  1264.         buttonTitle: 'Spacja o zerowej szerokości',
  1265.         buttonLabel: 'ZWSP'
  1266. }];
  1267.  
  1268. var wordfilters = [
  1269.         ['#nowocioty', 'STAROCIOTY PAMIĘTAJĄ'],
  1270.         ['#gimbo', 'xD'],
  1271.         ['#penis', 'pisiorek'],
  1272.         ['#wagina', 'cipuszka'],
  1273.         ['#m__b', 'groźny WYKOPEK wykryty'],
  1274.         ['#Lasoupeauxchoux', 'kapuśniaczek'],
  1275.         ['#homoś', 'pedał'],
  1276.         ['#korwinkrulempolski', 'kongres nowej prawicy'],
  1277.         ['#1%', 'groźny LEWAK wykryty'],
  1278.         ['#mylittlefaggot', 'PRZYJAŹŃ JEST MAGIĄ'],
  1279.         ['hizume', 'Mała Księżniczka'],
  1280.         ['#tetetka', 'ALE ZAPIERDALA'],
  1281.         ['/r/pcmasterrace', '/r/pcmasterrace']
  1282. ];
  1283. var boardsWithId = ['b', 'fz', 'z'];
  1284. var colors = [
  1285.         '#ff8080',
  1286.         '#ffdd80',
  1287.         '#80ffb7',
  1288.         '#80d0ff',
  1289.         '#c680ff',
  1290.         '#ffae80',
  1291.         '#d5ff80',
  1292.         '#80fffd',
  1293.         '#8097ff',
  1294.         '#ff80ca',
  1295.         '#ff7f7f',
  1296.         '#779aef',
  1297.         '#b0de6f',
  1298.         '#cc66c0',
  1299.         '#5cb9a9',
  1300.         '#f3bb79',
  1301.         '#8d71e2',
  1302.         '#6dd168',
  1303.         '#be5f7e',
  1304.         '#7bc8f6'
  1305. ];
  1306.  
  1307. var allowedFileExtensions = ['gif', 'jpeg', 'jpg', 'png', 'webm'];
  1308.  
  1309. /* internal configuration flags */
  1310. var roundedIdBackground = true;
  1311. var showPostCountNearHighlightPostsButton = true;
  1312. var showPostCountNearId = false;
  1313.  
  1314. showPostCountNearId = !enableHighlightPostsButton;
  1315. /// <reference path='./typeDefinitions/greasemonkey.d.ts'/>
  1316.  
  1317. var main = function () {
  1318.         window.kurahenPremium = new KurahenPremium();
  1319. };
  1320.  
  1321. if (navigator.userAgent.toLowerCase().indexOf('chrome/') > -1) {
  1322.         // Chrome/Chromium/Opera Next
  1323.         main();
  1324. } else {
  1325.         // Firefox and others
  1326.         window.addEventListener('DOMContentLoaded', main);
  1327. }