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