BugMeNot Everywhere

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

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

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