BugMeNot Everywhere

Add a list of login accounts from BugMeNot ( bugmenot.com ) on any website when focusing on username input

当前为 2018-02-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name BugMeNot Everywhere
  3. // @namespace https://greasyfork.org/users/37096/
  4. // @homepage https://greasyfork.org/scripts/35957/
  5. // @supportURL https://greasyfork.org/scripts/35957/feedback
  6. // @version 1.0.5
  7. // @description Add a list of login accounts from BugMeNot ( bugmenot.com ) on any website when focusing on username input
  8. // @author Hồng Minh Tâm
  9. // @icon http://bugmenot.com/favicon.ico
  10. // @include *
  11. // @grant GM_addStyle
  12. // @grant GM_xmlhttpRequest
  13. // @license GNU GPLv3
  14. // ==/UserScript==
  15.  
  16. (function () {
  17. 'use strict';
  18. GM_addStyle([
  19. '@import url(//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css);',
  20. '.bmn-list { display:none; list-style: none; border: 1px solid #ccc; padding: 0; margin: 0; background-color: #fff; position: fixed; cursor: default; z-index: 9999999999; box-sizing: border-box; overflow: auto; text-align: left; }',
  21. '.bmn-list.show { display:block; }',
  22. '.bmn-list .bmn-item { padding: 5px 10px; margin: 0; cursor: pointer; border-bottom: 1px solid #aaa; color: #333; }',
  23. '.bmn-list .bmn-item:last-child { border-bottom: 0; }',
  24. '.bmn-list .bmn-item:hover { background-color: #ddd; }',
  25. '.bmn-list .bmn-item .bmn-username { font-weight: 700; margin-bottom: 4px; }',
  26. '.bmn-list .bmn-item .bmn-password { margin-bottom: 4px; color: #666; }',
  27. '.bmn-list .bmn-item .bmn-success { display: inline-block; font-weight: 700; }',
  28. '.bmn-list .bmn-item .bmn-success.bmn-success-100 { color: rgb(0,198,0); }',
  29. '.bmn-list .bmn-item .bmn-success.bmn-success-90 { color: rgb(50,180,0); }',
  30. '.bmn-list .bmn-item .bmn-success.bmn-success-80 { color: rgb(99,164,0); }',
  31. '.bmn-list .bmn-item .bmn-success.bmn-success-70 { color: rgb(149,146,0); }',
  32. '.bmn-list .bmn-item .bmn-success.bmn-success-60 { color: rgb(199,129,0); }',
  33. '.bmn-list .bmn-item .bmn-success.bmn-success-50 { color: rgb(247,112,0); }',
  34. '.bmn-list .bmn-item .bmn-success.bmn-success-40 { color: rgb(247,90,0); }',
  35. '.bmn-list .bmn-item .bmn-success.bmn-success-30 { color: rgb(247,67,0); }',
  36. '.bmn-list .bmn-item .bmn-success.bmn-success-20 { color: rgb(247,45,0); }',
  37. '.bmn-list .bmn-item .bmn-success.bmn-success-10 { color: rgb(247,22,0); }',
  38. '.bmn-list .bmn-item .bmn-vote { display: inline-block; margin-left: 16px; float: right; }',
  39. '.bmn-list .bmn-no-logins-found { padding: 5px 10px; margin: 0; cursor: default; text-align: center; background-color: #a90000; color: #fff; }',
  40. ].join(''));
  41.  
  42. String.prototype.toDOM = function (isFull) {
  43. var parser = new DOMParser(),
  44. dom = parser.parseFromString(this, 'text/html');
  45. return isFull ? dom : dom.body.childNodes[0];
  46. };
  47.  
  48. function getOffset(element, noScroll) {
  49. var elementRect = element.getBoundingClientRect();
  50. return {
  51. left: elementRect.left,
  52. right: elementRect.right,
  53. top: elementRect.top,
  54. bottom: elementRect.bottom,
  55. };
  56. }
  57.  
  58. function handleEvent(func, data) {
  59. return function (event) {
  60. func.bind(this)(event, data);
  61. };
  62. }
  63.  
  64. var accounts = [];
  65. var inputUsernameCurrentEl, inputPasswordCurrentEl;
  66. var minHeightListBMN = 100;
  67.  
  68. GM_xmlhttpRequest({
  69. method: 'GET',
  70. url: 'http://bugmenot.com/view/' + location.hostname,
  71. headers: {
  72. 'Content-Type': 'application/x-www-form-urlencoded'
  73. },
  74. onload: function (response) {
  75. var bmnEl = response.responseText.toDOM(true);
  76. var accountEls = bmnEl.getElementsByClassName('account');
  77. for (var i = 0; i < accountEls.length; i++) {
  78. var accountEl = accountEls[i];
  79. var infoEl = accountEl.getElementsByTagName('kbd');
  80. var statsEl = accountEl.getElementsByClassName('stats')[1].getElementsByTagName('li');
  81. var account = {
  82. username: infoEl[0].innerHTML || '',
  83. password: infoEl[1].innerHTML || '',
  84. success: parseInt(statsEl[0].innerHTML.match(/\d+(?=%)/)[0]),
  85. vote: parseInt(statsEl[1].innerHTML.match(/\d+(?=\svotes)/)[0]),
  86. time: statsEl[2].innerHTML
  87. };
  88. accounts.push(account);
  89. }
  90. init();
  91. },
  92. onerror: function (response) {}
  93. });
  94.  
  95. function init() {
  96. var listBMNEl = document.createElement('ul');
  97. listBMNEl.classList.add('bmn-list');
  98. document.body.appendChild(listBMNEl);
  99.  
  100. function showListBMNEl() {
  101. listBMNEl.classList.add('show');
  102. }
  103.  
  104. function hideListBMNEl() {
  105. listBMNEl.classList.remove('show');
  106. }
  107.  
  108. if (accounts.length) {
  109. accounts.forEach(function (account, index) {
  110. var itemBMNEl = document.createElement('li');
  111. itemBMNEl.classList.add('bmn-item');
  112. var itemBMNElHTML = [
  113. '<div>',
  114. ' <i class="fa fa-user fa-fw"></i>',
  115. ' <span class="bmn-username">' + account.username + '</span>',
  116. '</div>',
  117. '<div>',
  118. ' <i class="fa fa-key fa-fw"></i>',
  119. ' <span class="bmn-password">' + account.password + '</span>',
  120. '</div>',
  121. '<div>',
  122. ' <div class="bmn-success ' + getClassSuccess(account.success) + '">' + account.success + '%</div>',
  123. ' <div class="bmn-vote">' + account.vote + ' votes</div>',
  124. '</div>',
  125. // ',<div class="time">' + account.time + '</div>',
  126. ].join('');
  127. itemBMNEl.innerHTML = itemBMNElHTML;
  128. itemBMNEl.title = [
  129. 'Username: ' + account.username,
  130. 'Password: ' + account.password,
  131. '',
  132. account.success + '% success rate',
  133. account.vote + ' votes',
  134. account.time
  135. ].join('\n');
  136. itemBMNEl.onmousedown = handleEvent(onMouseDownItem);
  137. itemBMNEl.onclick = handleEvent(onClickItem, account);
  138. itemBMNEl.onmouseover = handleEvent(onMouseOverItem, account);
  139. itemBMNEl.onmouseout = handleEvent(onMouseOutItem);
  140. listBMNEl.appendChild(itemBMNEl);
  141. });
  142. } else {
  143. var itemBMNNoLoginsFoundEl = document.createElement('li');
  144. itemBMNNoLoginsFoundEl.classList.add('bmn-no-logins-found');
  145. itemBMNNoLoginsFoundEl.innerHTML = 'No logins found';
  146. listBMNEl.appendChild(itemBMNNoLoginsFoundEl);
  147. }
  148.  
  149. window.onscroll = function (event) {
  150. if (inputUsernameCurrentEl) {
  151. addStyleListBMNEl(inputUsernameCurrentEl);
  152. }
  153. };
  154.  
  155. window.onresize = function (event) {
  156. if (inputUsernameCurrentEl) {
  157. addStyleListBMNEl(inputUsernameCurrentEl);
  158. }
  159. };
  160.  
  161. var enableMouseOut = true;
  162.  
  163. function setValueInput(inputUsernameEl, inputPasswordEl, username, password) {
  164. inputUsernameEl.value = username;
  165. inputPasswordEl.value = password;
  166. }
  167.  
  168. function onMouseDownItem(event) {
  169. event.preventDefault();
  170. }
  171.  
  172. function onClickItem(event, account) {
  173. enableMouseOut = false;
  174. if (inputUsernameCurrentEl && inputPasswordCurrentEl) {
  175. setValueInput(inputUsernameCurrentEl, inputPasswordCurrentEl, account.username, account.password);
  176. hideListBMNEl();
  177. }
  178. }
  179.  
  180. function onMouseOverItem(event, account) {
  181. if (inputUsernameCurrentEl && inputPasswordCurrentEl) {
  182. setValueInput(inputUsernameCurrentEl, inputPasswordCurrentEl, account.username, account.password);
  183. }
  184. }
  185.  
  186. function onMouseOutItem(event) {
  187. if (!enableMouseOut) {
  188. enableMouseOut = true;
  189. return;
  190. }
  191. if (inputUsernameCurrentEl && inputPasswordCurrentEl) {
  192. setValueInput(inputUsernameCurrentEl, inputPasswordCurrentEl, '', '');
  193. }
  194. }
  195.  
  196. function getClassSuccess(success) {
  197. if (success > 91) return 'bmn-success-100';
  198. else if (success > 81) return 'bmn-success-90';
  199. else if (success > 71) return 'bmn-success-80';
  200. else if (success > 61) return 'bmn-success-70';
  201. else if (success > 51) return 'bmn-success-60';
  202. else if (success > 31) return 'bmn-success-50';
  203. else if (success > 21) return 'bmn-success-30';
  204. else if (success > 11) return 'bmn-success-20';
  205. else return 'bmn-success-10';
  206. }
  207.  
  208. function addStyleListBMNEl(inputEl) {
  209. listBMNEl.style.width = inputEl.offsetWidth + 'px';
  210. var offsetTarget = getOffset(inputEl);
  211. var windowHeight = document.documentElement.clientHeight;
  212. if (offsetTarget.top >= minHeightListBMN) {
  213. listBMNEl.style.bottom = (windowHeight - offsetTarget.top) + 'px';
  214. listBMNEl.style.top = '';
  215. listBMNEl.style.left = offsetTarget.left + 'px';
  216. listBMNEl.style.maxHeight = offsetTarget.top + 'px';
  217. } else {
  218. listBMNEl.style.top = offsetTarget.bottom + 'px';
  219. listBMNEl.style.bottom = '';
  220. listBMNEl.style.left = offsetTarget.left + 'px';
  221. listBMNEl.style.maxHeight = (windowHeight - offsetTarget.bottom) + 'px';
  222. }
  223. }
  224.  
  225. function onFocusInput(event, data) {
  226. inputUsernameCurrentEl = data.inputUsernameEl;
  227. inputPasswordCurrentEl = data.inputPasswordEl;
  228. addStyleListBMNEl(inputUsernameCurrentEl);
  229. showListBMNEl();
  230. }
  231.  
  232. function onBlurInput(event) {
  233. if (!event.target.isSameNode(document.activeElement)) {
  234. hideListBMNEl();
  235. }
  236. }
  237.  
  238. function onInputInput(event) {
  239. enableMouseOut = false;
  240. hideListBMNEl();
  241. }
  242.  
  243. function getInputEls() {
  244. var inputEls = [];
  245. var inputElTemps = document.getElementsByTagName('input');
  246. var inputElTemp;
  247. for (var i = 0; i < inputElTemps.length; i++) {
  248. inputElTemp = inputElTemps[i];
  249. switch (inputElTemp.type) {
  250. case "text":
  251. case "email":
  252. case "tel":
  253. case "password":
  254. inputEls.push(inputElTemp);
  255. break;
  256. }
  257. }
  258. return inputEls;
  259. }
  260.  
  261. var inputEls = getInputEls();
  262. for (var i = 0; i < inputEls.length; i++) {
  263. if (inputEls[i].type === 'password') {
  264. if ((inputEls[i + 1] && inputEls[i + 1].type === 'password')) {
  265. continue;
  266. }
  267.  
  268. if (inputEls[i - 1]) {
  269. if (inputEls[i - 1].type === 'password') {
  270. continue;
  271. } else {
  272. var inputUsernameEl = inputEls[i - 1];
  273. var inputPasswordEl = inputEls[i];
  274. var data = {
  275. inputUsernameEl: inputUsernameEl,
  276. inputPasswordEl: inputPasswordEl
  277. };
  278. inputUsernameEl.onclick = handleEvent(onFocusInput, data);
  279. inputUsernameEl.onfocus = handleEvent(onFocusInput, data);
  280. inputUsernameEl.onblur = handleEvent(onBlurInput);
  281. inputUsernameEl.oninput = handleEvent(onInputInput);
  282. if (inputUsernameEl.isSameNode(document.activeElement)) onFocusInput(undefined, data);
  283. }
  284. }
  285. }
  286. }
  287. }
  288. })();