vk.com mark as read

mark posts as read (помечает посты как прочитанные)

目前为 2017-03-03 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name vk.com mark as read
  3. // @namespace limizin.userscripts
  4. // @description mark posts as read (помечает посты как прочитанные)
  5. // @include https://vk.com*
  6. // @version 1.1
  7. // @grant GM_setValue
  8. // @grant GM_getValue
  9. // ==/UserScript==
  10. (function () {
  11. postwall = document.getElementById('page_wall_posts');
  12. if (!postwall)
  13. return;
  14. if (!document.querySelector('style#usernameReadPost')) {
  15. stl = document.querySelector('head').appendChild(document.createElement('style'));
  16. stl.id = 'usernameReadPost';
  17. stl.innerHTML = '.usernameReadPost, .usernameReadPost ~ * {background-color: silver !important;}';
  18. } //----
  19.  
  20. function hashCode(value) {
  21. var hash = 0;
  22. if (value.length == 0) return hash;
  23. for (i = 0; i < value.length; i++) {
  24. char = value.charCodeAt(i);
  25. hash = ((hash << 5) - hash) + char;
  26. hash = hash & hash; // Convert to 32bit integer
  27. }
  28. return hash;
  29. }
  30. function reverse(value) {
  31. return value.split('').reverse().join('');
  32. }
  33. storageKey = 'usernameReadPost/' + hashCode(location.pathname)+hashCode(reverse(location.pathname));
  34. //top_shadow_post_id = window.localStorage.getItem(storageKey);
  35. top_shadow_post_id = GM_getValue(storageKey);
  36. //---
  37. function markRead() {
  38. sel = document.getSelection();
  39. if (!sel.isCollapsed) {
  40. var xpath = './ancestor::div[contains(@class, "post") and not(@id="page_wall_posts")]';
  41. var post = document.evaluate(xpath, sel.focusNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
  42. if (post) {
  43. post.className += ' usernameReadPost';
  44. //window.localStorage.setItem(storageKey, post.getAttribute('id'));
  45. GM_setValue(storageKey, post.getAttribute('id'));
  46. var prevPostsXpath = './preceding-sibling::div[contains(@class, "post")]';
  47. var prevPosts = document.evaluate(prevPostsXpath, post, null, XPathResult.ANY_TYPE, null);
  48. var prevPost = prevPosts.iterateNext();
  49. while (prevPost) {
  50. prevPost.className = prevPost.className.replace('usernameReadPost', '');
  51. prevPost = prevPosts.iterateNext();
  52. }
  53. }
  54. }
  55. }
  56. function scrollToRead(event) {
  57. var post = document.querySelector('div.usernameReadPost');
  58. if (post) {
  59. var postYOffset = post.offsetTop;
  60. var median = window.innerHeight / 2;
  61. var scrollTo = postYOffset - median;
  62. if (scrollTo < 0) {
  63. scrollTo = 0;
  64. }
  65. window.scrollTo(0, scrollTo);
  66. }
  67. }
  68. shadow = false;
  69. function shadowRead(event) {
  70. if (shadow || !top_shadow_post_id)
  71. return;
  72. var post = document.getElementById(top_shadow_post_id);
  73. if (post) {
  74. post.className += ' usernameReadPost';
  75. shadow = true;
  76. postwall.removeEventListener('DOMNodeInserted', shadowRead);
  77. }
  78. }
  79. function createButton(content, handler, title) {
  80. var btn = document.createElement('button');
  81. btn.textContent = content;
  82. btn.onclick = handler;
  83. btn.title = title;
  84. btn.style.backgroundColor = '#507299';
  85. btn.style.color = '#ffffff';
  86. btn.style.border = 'thin solid #C4C4C4';
  87. if (navigator.userAgent.toLowerCase().indexOf('firefox') > - 1) {
  88. btn.style.paddingBottom = '2px';
  89. }
  90. btn.style.cursor = 'pointer';
  91. return btn;
  92. }
  93. var buttonBlock = document.createElement('div');
  94. buttonBlock.style.display = 'inline';
  95. buttonBlock.style.marginLeft = '-60px';
  96. buttonBlock.style.marginRight = '7px';
  97. buttonBlock.style.marginTop = '10px';
  98. buttonBlock.style.float = 'left';
  99. //buttonBlock.style = 'margin-left: -60px; margin-right:7px; ';
  100. var scrollToReadBtn = createButton('>', scrollToRead, 'scroll to read');
  101. buttonBlock.appendChild(scrollToReadBtn);
  102. //mark read button
  103. var markReadBtn = createButton('+', markRead, 'mark as read');
  104. markReadBtn.style.borderLeft = 'none';
  105. buttonBlock.appendChild(markReadBtn);
  106. document.querySelector('div.head_nav_item').appendChild(buttonBlock);
  107. //post wall
  108. postwall.addEventListener('DOMNodeInserted', shadowRead);
  109. //run
  110. shadowRead(null);
  111. }) ();