BugMeNot Everywhere

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

目前为 2017-12-10 提交的版本,查看 最新版本

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